VM: Separate precompilation-specific code, make flags const.

Move optimizations for precompilation into separate file.

Remove precompilation-specific code from flow_graph_optimizer.cc.

Add precompilation-flags: They are const in the precompiled runtime. Started moving flags to use the new flag-definition macros.

Add libdart_lib_precompiled target.

Define PRECOMPILED_RUNTIME_MACRO in more places (dart_precompiled_runtime)

BUG=
R=rmacnak@google.com

Review URL: https://codereview.chromium.org/1714743002 .
This commit is contained in:
Florian Schneider 2016-02-23 08:48:08 -08:00
parent 3df7b0c072
commit b870dafa4f
32 changed files with 3242 additions and 197 deletions

View file

@ -752,6 +752,9 @@
'<(resources_cc_file)',
'<(observatory_assets_cc_file)',
],
'defines': [
'DART_PRECOMPILED_RUNTIME',
],
'conditions': [
['OS=="win"', {
'link_settings': {

View file

@ -95,7 +95,7 @@
'target_name': 'libdart_precompiled_runtime',
'type': 'static_library',
'dependencies': [
'libdart_lib',
'libdart_lib_precompiled_runtime',
'libdart_vm_precompiled_runtime',
'libdouble_conversion',
'generate_version_cc_file#host',

View file

@ -10,6 +10,7 @@
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/port.h"
@ -20,8 +21,6 @@ namespace dart {
#ifndef PRODUCT
DECLARE_FLAG(bool, lazy_dispatchers);
#define PROPAGATE_IF_MALFORMED(type) \
if (type.IsMalformed()) { \
Exceptions::PropagateError(Error::Handle(type.error())); \

2856
runtime/vm/aot_optimizer.cc Normal file

File diff suppressed because it is too large Load diff

188
runtime/vm/aot_optimizer.h Normal file
View file

@ -0,0 +1,188 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_AOT_OPTIMIZER_H_
#define VM_AOT_OPTIMIZER_H_
#include "vm/intermediate_language.h"
#include "vm/flow_graph.h"
namespace dart {
class CSEInstructionMap;
template <typename T> class GrowableArray;
class ParsedFunction;
class RawBool;
class AotOptimizer : public FlowGraphVisitor {
public:
AotOptimizer(
FlowGraph* flow_graph,
bool use_speculative_inlining,
GrowableArray<intptr_t>* inlining_black_list)
: FlowGraphVisitor(flow_graph->reverse_postorder()),
flow_graph_(flow_graph),
use_speculative_inlining_(use_speculative_inlining),
inlining_black_list_(inlining_black_list) {
ASSERT(!use_speculative_inlining || (inlining_black_list != NULL));
}
virtual ~AotOptimizer() {}
FlowGraph* flow_graph() const { return flow_graph_; }
// Add ICData to InstanceCalls, so that optimizations can be run on them.
// TODO(srdjan): StaticCals as well?
void PopulateWithICData();
// Use ICData to optimize, replace or eliminate instructions.
void ApplyICData();
// Use propagated class ids to optimize, replace or eliminate instructions.
void ApplyClassIds();
// Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
// shift can be a truncating Smi shift-left and result is always Smi.
// Merge instructions (only per basic-block).
void TryOptimizePatterns();
virtual void VisitStaticCall(StaticCallInstr* instr);
virtual void VisitInstanceCall(InstanceCallInstr* instr);
virtual void VisitAllocateContext(AllocateContextInstr* instr);
virtual void VisitLoadCodeUnits(LoadCodeUnitsInstr* instr);
void InsertBefore(Instruction* next,
Instruction* instr,
Environment* env,
FlowGraph::UseKind use_kind) {
flow_graph_->InsertBefore(next, instr, env, use_kind);
}
private:
// Attempt to build ICData for call using propagated class-ids.
bool TryCreateICData(InstanceCallInstr* call);
const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid);
void SpecializePolymorphicInstanceCall(PolymorphicInstanceCallInstr* call);
bool TryReplaceWithIndexedOp(InstanceCallInstr* call);
bool TryReplaceWithBinaryOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryReplaceWithUnaryOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryReplaceWithEqualityOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryReplaceWithRelationalOp(InstanceCallInstr* call, Token::Kind op_kind);
bool TryInlineInstanceGetter(InstanceCallInstr* call,
bool allow_check = true);
bool TryInlineInstanceSetter(InstanceCallInstr* call,
const ICData& unary_ic_data,
bool allow_check = true);
bool TryInlineInstanceMethod(InstanceCallInstr* call);
bool TryInlineFloat32x4Constructor(StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind);
bool TryInlineFloat64x2Constructor(StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind);
bool TryInlineInt32x4Constructor(StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind);
bool TryInlineFloat32x4Method(InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind);
bool TryInlineFloat64x2Method(InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind);
bool TryInlineInt32x4Method(InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind);
void ReplaceWithInstanceOf(InstanceCallInstr* instr);
bool TypeCheckAsClassEquality(const AbstractType& type);
void ReplaceWithTypeCast(InstanceCallInstr* instr);
bool TryReplaceInstanceCallWithInline(InstanceCallInstr* call);
// Insert a check of 'to_check' determined by 'unary_checks'. If the
// check fails it will deoptimize to 'deopt_id' using the deoptimization
// environment 'deopt_environment'. The check is inserted immediately
// before 'insert_before'.
void AddCheckClass(Definition* to_check,
const ICData& unary_checks,
intptr_t deopt_id,
Environment* deopt_environment,
Instruction* insert_before);
Instruction* GetCheckClass(Definition* to_check,
const ICData& unary_checks,
intptr_t deopt_id,
TokenPosition token_pos);
// Insert a Smi check if needed.
void AddCheckSmi(Definition* to_check,
intptr_t deopt_id,
Environment* deopt_environment,
Instruction* insert_before);
// Add a class check for a call's first argument immediately before the
// call, using the call's IC data to determine the check, and the call's
// deopt ID and deoptimization environment if the check fails.
void AddReceiverCheck(InstanceCallInstr* call);
void ReplaceCall(Definition* call, Definition* replacement);
bool InstanceCallNeedsClassCheck(InstanceCallInstr* call,
RawFunction::Kind kind) const;
bool InlineFloat32x4Getter(InstanceCallInstr* call,
MethodRecognizer::Kind getter);
bool InlineFloat64x2Getter(InstanceCallInstr* call,
MethodRecognizer::Kind getter);
bool InlineInt32x4Getter(InstanceCallInstr* call,
MethodRecognizer::Kind getter);
bool InlineFloat32x4BinaryOp(InstanceCallInstr* call,
Token::Kind op_kind);
bool InlineInt32x4BinaryOp(InstanceCallInstr* call,
Token::Kind op_kind);
bool InlineFloat64x2BinaryOp(InstanceCallInstr* call,
Token::Kind op_kind);
bool InlineImplicitInstanceGetter(InstanceCallInstr* call, bool allow_check);
RawBool* InstanceOfAsBool(const ICData& ic_data,
const AbstractType& type,
ZoneGrowableArray<intptr_t>* results) const;
void ReplaceWithMathCFunction(InstanceCallInstr* call,
MethodRecognizer::Kind recognized_kind);
void OptimizeLeftShiftBitAndSmiOp(Definition* bit_and_instr,
Definition* left_instr,
Definition* right_instr);
void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);
void TryMergeMathUnary(GrowableArray<MathUnaryInstr*>* merge_candidates);
void AppendExtractNthOutputForMerged(Definition* instr, intptr_t ix,
Representation rep, intptr_t cid);
bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
void InstanceCallNoopt(InstanceCallInstr* instr);
RawField* GetField(intptr_t class_id, const String& field_name);
Thread* thread() const { return flow_graph_->thread(); }
Isolate* isolate() const { return flow_graph_->isolate(); }
Zone* zone() const { return flow_graph_->zone(); }
const Function& function() const { return flow_graph_->function(); }
bool IsBlackListedForInlining(intptr_t deopt_id);
FlowGraph* flow_graph_;
const bool use_speculative_inlining_;
GrowableArray<intptr_t>* inlining_black_list_;
DISALLOW_COPY_AND_ASSIGN(AotOptimizer);
};
} // namespace dart
#endif // VM_AOT_OPTIMIZER_H_

View file

@ -18,7 +18,6 @@ namespace dart {
DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
DECLARE_FLAG(bool, use_cha_deopt);
bool ClassFinalizer::AllClassesFinalized() {

View file

@ -64,8 +64,6 @@ DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, enable_inlining_annotations);
DECLARE_FLAG(bool, trace_compiler);
DECLARE_FLAG(bool, trace_field_guards);
DECLARE_FLAG(bool, trace_optimization);
DECLARE_FLAG(bool, trace_optimizing_compiler);
DECLARE_FLAG(int, max_polymorphic_checks);
DECLARE_FLAG(bool, precompilation);
@ -81,7 +79,6 @@ DEFINE_FLAG(int, deoptimize_every, 0,
"Deoptimize on every N stack overflow checks");
DEFINE_FLAG(charp, deoptimize_filter, NULL,
"Deoptimize in named function on stack overflow checks");
DEFINE_FLAG(bool, lazy_dispatchers, true, "Lazily generate dispatchers");
#ifdef DEBUG
DEFINE_FLAG(charp, gc_at_instance_allocation, NULL,

View file

@ -17,8 +17,6 @@
namespace dart {
DECLARE_FLAG(bool, lazy_dispatchers);
// A cache of VM heap allocated arguments descriptors.
RawArray* ArgumentsDescriptor::cached_args_descriptors_[kCachedDescriptorCount];

View file

@ -12,8 +12,15 @@
// * D ebug flags: Can only be set in debug VMs, which also have assertions
// enabled.
// * R elease flags: Generally available flags except when building product.
#define FLAG_LIST(P, R, D) \
// * pre C ompile flags: Generally available flags except when building product
// or precompiled runtime.
//
// Usage:
// P(name, type, default_value, comment)
// D(name, type, default_value, comment)
// R(name, product_value, type, default_value, comment)
// C(name, precompiled_value, product_value, type, default_value, comment)
#define FLAG_LIST(P, R, D, C) \
R(dedup_instructions, true, bool, false, \
"Canonicalize instructions when precompiling.") \
R(disable_alloc_stubs_after_gc, false, bool, false, \
@ -28,8 +35,22 @@ R(enable_mirrors, false, bool, true, \
"Disable to make importing dart:mirrors an error.") \
R(gc_at_alloc, false, bool, false, \
"GC at every allocation.") \
P(getter_setter_ratio, int, 13, \
"Ratio of getter/setter usage used for double field unboxing heuristics") \
P(guess_icdata_cid, bool, true, \
"Artificially create type feedback for arithmetic etc. operations") \
C(lazy_dispatchers, false, true, bool, true, \
"Generate dispatchers lazily") \
P(max_polymorphic_checks, int, 4, \
"Maximum number of polymorphic check, otherwise it is megamorphic.") \
P(max_equality_polymorphic_checks, int, 32, \
"Maximum number of polymorphic checks in equality operator,") \
P(merge_sin_cos, bool, false, \
"Merge sin/cos into sincos") \
P(new_gen_ext_limit, int, 64, \
"maximum total external size (MB) in new gen before triggering GC") \
C(polymorphic_with_deopt, false, true, bool, true, \
"Polymorphic calls with deoptimization / megamorphic call") \
R(pretenure_all, false, bool, false, \
"Global pretenuring (for testing).") \
P(pretenure_interval, int, 10, \
@ -54,10 +75,20 @@ R(support_coverage, false, bool, true, \
"Support code coverage.") \
R(support_timeline, false, bool, true, \
"Support timeline.") \
D(trace_cha, bool, false, \
"Trace CHA operations") \
D(trace_field_guards, bool, false, \
"Trace changes in field's cids.") \
D(trace_handles, bool, false, \
"Traces allocation of handles.") \
D(trace_optimization, bool, false, \
"Print optimization details."); \
D(trace_zones, bool, false, \
"Traces allocation sizes in the zone.") \
P(truncating_left_shift, bool, true, \
"Optimize left shift to truncate if possible") \
C(use_cha_deopt, false, true, bool, true, \
"Use class hierarchy analysis even if it can cause deoptimization.") \
P(verbose_gc, bool, false, \
"Enables verbose GC.") \
P(verbose_gc_hdr, int, 40, \

View file

@ -30,24 +30,52 @@ DEFINE_FLAG(bool, ignore_unrecognized_flags, false,
#define DEBUG_FLAG_MARCO(name, type, default_value, comment)
#endif // defined(DEBUG)
#if defined(PRODUCT)
#if defined(PRODUCT) && defined(DART_PRECOMPILED_RUNTIME)
// Nothing to be done for the product flag definitions.
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment)
#else // defined(PRODUCT)
// Nothing to be done for the precompilation flag definitions.
#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
default_value, comment)
#elif defined(PRODUCT) // !PRECOMPILED
// Nothing to be done for the product flag definitions.
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment)
#elif defined(DART_PRECOMPILED_RUNTIME) // !PRODUCT
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
type FLAG_##name = Flags::Register_##type(&FLAG_##name, \
#name, \
default_value, \
comment);
#endif // defined(PRODUCT)
// Nothing to be done for the precompilation flag definitions.
#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
default_value, comment)
#else // !PRODUCT && !PRECOMPILED
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
type FLAG_##name = Flags::Register_##type(&FLAG_##name, \
#name, \
default_value, \
comment);
#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
default_value, comment) \
type FLAG_##name = Flags::Register_##type(&FLAG_##name, \
#name, \
default_value, \
comment);
#endif
// Define all of the non-product flags here.
FLAG_LIST(PRODUCT_FLAG_MARCO, RELEASE_FLAG_MARCO, DEBUG_FLAG_MARCO)
FLAG_LIST(PRODUCT_FLAG_MARCO,
RELEASE_FLAG_MARCO,
DEBUG_FLAG_MARCO,
PRECOMPILE_FLAG_MARCO)
#undef RELEASE_FLAG_MARCO
#undef DEBUG_FLAG_MARCO
#undef PRODUCT_FLAG_MARCO
#undef PRECOMPILE_FLAG_MARCO
bool Flags::initialized_ = false;

View file

@ -110,23 +110,47 @@ class Flags {
const type FLAG_##name = default_value;
#endif // defined(DEBUG)
#if defined(PRODUCT)
#if defined(PRODUCT) && defined(DART_PRECOMPILED_RUNTIME)
#define RELEASE_FLAG_MARCO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = product_value;
#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = precompiled_value;
#elif defined(PRODUCT) // !PRECOMPILED
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
const type FLAG_##name = product_value;
#else // defined(PRODUCT)
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
default_value, comment) \
extern type FLAG_##name;
#endif // defined(PRODUCT)
#elif defined(DART_PRECOMPILED_RUNTIME) // !PRODUCT
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
extern type FLAG_##name;
#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = precompiled_value;
#else // !PRODUCT && !PRECOMPILED
#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
extern type FLAG_##name;
#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
default_value, comment) \
extern type FLAG_##name;
#endif
// Now declare all flags here.
FLAG_LIST(PRODUCT_FLAG_MARCO, RELEASE_FLAG_MARCO, DEBUG_FLAG_MARCO)
FLAG_LIST(PRODUCT_FLAG_MARCO,
RELEASE_FLAG_MARCO,
DEBUG_FLAG_MARCO,
PRECOMPILE_FLAG_MARCO)
#undef RELEASE_FLAG_MARCO
#undef DEBUG_FLAG_MARCO
#undef PRODUCT_FLAG_MARCO
#undef PRECOMPILE_FLAG_MARCO
} // namespace dart

View file

@ -21,7 +21,6 @@ DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass.");
DEFINE_FLAG(bool, prune_dead_locals, true, "optimize dead locals away");
DECLARE_FLAG(bool, emit_edge_counters);
DECLARE_FLAG(bool, reorder_basic_blocks);
DECLARE_FLAG(bool, trace_optimization);
DECLARE_FLAG(bool, verify_compiler);

View file

@ -13,6 +13,7 @@
#include "vm/debugger.h"
#include "vm/deopt_instructions.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/flow_graph_allocator.h"
#include "vm/il_printer.h"
#include "vm/intrinsifier.h"
@ -39,9 +40,6 @@ DEFINE_FLAG(int, min_optimization_counter_threshold, 5000,
"The minimum invocation count for a function.");
DEFINE_FLAG(int, optimization_counter_scale, 2000,
"The scale of invocation count, by size of the function.");
DEFINE_FLAG(bool, polymorphic_with_deopt, true,
"Polymorphic calls can be generated so that failure either causes "
"deoptimization or falls through to a megamorphic call");
DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
DEFINE_FLAG(bool, trace_inlining_intervals, false,
"Inlining interval diagnostics");
@ -65,10 +63,8 @@ DECLARE_FLAG(int, reoptimization_counter_threshold);
DECLARE_FLAG(int, stacktrace_every);
DECLARE_FLAG(charp, stacktrace_filter);
DECLARE_FLAG(bool, use_field_guards);
DECLARE_FLAG(bool, use_cha_deopt);
DECLARE_FLAG(bool, use_osr);
DECLARE_FLAG(bool, print_stop_message);
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, interpret_irregexp);
DECLARE_FLAG(bool, link_natives_lazily);
DECLARE_FLAG(bool, trace_compiler);
@ -90,7 +86,6 @@ static void PrecompilationModeHandler(bool value) {
FLAG_precompilation = true;
FLAG_always_megamorphic_calls = true;
FLAG_polymorphic_with_deopt = false;
FLAG_optimization_counter_threshold = -1;
FLAG_use_field_guards = false;
FLAG_use_osr = false;
@ -103,14 +98,10 @@ static void PrecompilationModeHandler(bool value) {
FLAG_load_deferred_eagerly = true;
FLAG_deoptimize_alot = false; // Used in some tests.
FLAG_deoptimize_every = 0; // Used in some tests.
// Precompilation finalizes all classes and thus allows CHA optimizations.
// Do not require CHA triggered deoptimization.
FLAG_use_cha_deopt = false;
// Calling the PrintStopMessage stub is not supported in precompiled code
// since it is done at places where no pool pointer is loaded.
FLAG_print_stop_message = false;
FLAG_lazy_dispatchers = false;
FLAG_interpret_irregexp = true;
#ifndef PRODUCT
FLAG_enable_mirrors = false;
@ -137,6 +128,17 @@ static void PrecompilationModeHandler(bool value) {
// while precompilation has only one.
FLAG_background_compilation = false;
FLAG_collect_dynamic_function_names = true;
#if !defined(DART_PRECOMPILED_RUNTIME)
FLAG_lazy_dispatchers = false;
FLAG_polymorphic_with_deopt = false;
// Precompilation finalizes all classes and thus allows CHA optimizations.
// Do not require CHA triggered deoptimization.
FLAG_use_cha_deopt = false;
#else
COMPILE_ASSERT(!FLAG_lazy_dispatchers);
COMPILE_ASSERT(!FLAG_polymorphic_with_deopt);
COMPILE_ASSERT(!FLAG_use_cha_deopt);
#endif
}
}

View file

@ -4,6 +4,7 @@
#include "vm/flow_graph_inliner.h"
#include "vm/aot_optimizer.h"
#include "vm/block_scheduler.h"
#include "vm/branch_optimizer.h"
#include "vm/compiler.h"
@ -61,7 +62,6 @@ DEFINE_FLAG(bool, enable_inlining_annotations, false,
DECLARE_FLAG(bool, compiler_stats);
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
DECLARE_FLAG(bool, polymorphic_with_deopt);
DECLARE_FLAG(bool, precompilation);
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@ -790,10 +790,10 @@ class CallSiteInliner : public ValueObject {
CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer);
// TODO(fschneider): Improve suppression of speculative inlining.
// Deopt-ids overlap between caller and callee.
FlowGraphOptimizer optimizer(callee_graph,
inliner_->use_speculative_inlining_,
inliner_->inlining_black_list_);
if (FLAG_precompilation) {
AotOptimizer optimizer(callee_graph,
inliner_->use_speculative_inlining_,
inliner_->inlining_black_list_);
optimizer.PopulateWithICData();
optimizer.ApplyClassIds();
@ -801,14 +801,26 @@ class CallSiteInliner : public ValueObject {
FlowGraphTypePropagator::Propagate(callee_graph);
DEBUG_ASSERT(callee_graph->VerifyUseLists());
}
optimizer.ApplyICData();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
// Optimize (a << b) & c patterns, merge instructions. Must occur
// before 'SelectRepresentations' which inserts conversion nodes.
optimizer.TryOptimizePatterns();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
optimizer.ApplyICData();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
// Optimize (a << b) & c patterns, merge instructions. Must occur
// before 'SelectRepresentations' which inserts conversion nodes.
optimizer.TryOptimizePatterns();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
} else {
FlowGraphOptimizer optimizer(callee_graph,
inliner_->use_speculative_inlining_,
inliner_->inlining_black_list_);
optimizer.ApplyICData();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
// Optimize (a << b) & c patterns, merge instructions. Must occur
// before 'SelectRepresentations' which inserts conversion nodes.
optimizer.TryOptimizePatterns();
DEBUG_ASSERT(callee_graph->VerifyUseLists());
}
}
if (FLAG_support_il_printer && FLAG_trace_inlining &&
@ -1508,9 +1520,6 @@ static Instruction* AppendInstruction(Instruction* first,
bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
const Function& target) {
FlowGraphOptimizer optimizer(owner_->caller_graph(),
false, // Speculative inlining not applicable.
NULL);
TargetEntryInstr* entry;
Definition* last;
// Replace the receiver argument with a redefinition to prevent code from

View file

@ -20,7 +20,6 @@
#include "vm/intermediate_language.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/precompiler.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
@ -28,28 +27,6 @@
namespace dart {
DEFINE_FLAG(int, getter_setter_ratio, 13,
"Ratio of getter/setter usage used for double field unboxing heuristics");
DEFINE_FLAG(bool, guess_icdata_cid, true,
"Artificially create type feedback for arithmetic etc. operations"
" by guessing the other unknown argument cid");
DEFINE_FLAG(int, max_polymorphic_checks, 4,
"Maximum number of polymorphic check, otherwise it is megamorphic.");
DEFINE_FLAG(int, max_equality_polymorphic_checks, 32,
"Maximum number of polymorphic checks in equality operator,"
" otherwise use megamorphic dispatch.");
DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos");
DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
DEFINE_FLAG(bool, truncating_left_shift, true,
"Optimize left shift to truncate if possible");
DEFINE_FLAG(bool, use_cha_deopt, true,
"Use class hierarchy analysis even if it can cause deoptimization.");
DECLARE_FLAG(bool, precompilation);
DECLARE_FLAG(bool, polymorphic_with_deopt);
DECLARE_FLAG(bool, trace_cha);
DECLARE_FLAG(bool, trace_field_guards);
// Quick access to the current isolate and zone.
#define I (isolate())
#define Z (zone())
@ -75,34 +52,6 @@ void FlowGraphOptimizer::ApplyICData() {
}
void FlowGraphOptimizer::PopulateWithICData() {
ASSERT(current_iterator_ == NULL);
for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
!block_it.Done();
block_it.Advance()) {
ForwardInstructionIterator it(block_it.Current());
for (; !it.Done(); it.Advance()) {
Instruction* instr = it.Current();
if (instr->IsInstanceCall()) {
InstanceCallInstr* call = instr->AsInstanceCall();
if (!call->HasICData()) {
const Array& arguments_descriptor =
Array::Handle(zone(),
ArgumentsDescriptor::New(call->ArgumentCount(),
call->argument_names()));
const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New(
function(), call->function_name(),
arguments_descriptor, call->deopt_id(),
call->checked_argument_count()));
call->set_ic_data(&ic_data);
}
}
}
current_iterator_ = NULL;
}
}
// Optimize instance calls using cid. This is called after optimizer
// converted instance calls to instructions. Any remaining
// instance calls are either megamorphic calls, cannot be optimized or
@ -218,29 +167,6 @@ bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
return true;
}
#ifdef DART_PRECOMPILER
if (FLAG_precompilation &&
(isolate()->object_store()->unique_dynamic_targets() != Array::null())) {
// Check if the target is unique.
Function& target_function = Function::Handle(Z);
Precompiler::GetUniqueDynamicTarget(
isolate(), call->function_name(), &target_function);
// Calls with named arguments must be resolved/checked at runtime.
String& error_message = String::Handle(Z);
if (!target_function.IsNull() &&
!target_function.HasOptionalNamedParameters() &&
target_function.AreValidArgumentCounts(call->ArgumentCount(), 0,
&error_message)) {
const intptr_t cid = Class::Handle(Z, target_function.Owner()).id();
const ICData& ic_data = ICData::ZoneHandle(Z,
ICData::NewFrom(*call->ic_data(), 1));
ic_data.AddReceiverCheck(cid, target_function);
call->set_ic_data(&ic_data);
return true;
}
}
#endif
// Check if getter or setter in function's class and class is currently leaf.
if (FLAG_guess_icdata_cid &&
((call->token_kind() == Token::kGET) ||
@ -2058,10 +1984,6 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind) {
if (FLAG_precompilation) {
// Cannot handle unboxed instructions.
return false;
}
if (!ShouldInlineSimd()) {
return false;
}
@ -2105,10 +2027,6 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind) {
if (FLAG_precompilation) {
// Cannot handle unboxed instructions.
return false;
}
if (!ShouldInlineSimd()) {
return false;
}
@ -2144,10 +2062,6 @@ bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
bool FlowGraphOptimizer::TryInlineInt32x4Constructor(
StaticCallInstr* call,
MethodRecognizer::Kind recognized_kind) {
if (FLAG_precompilation) {
// Cannot handle unboxed instructions.
return false;
}
if (!ShouldInlineSimd()) {
return false;
}
@ -2938,11 +2852,6 @@ void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) {
// Tries to optimize instance call by replacing it with a faster instruction
// (e.g, binary op, field load, ..).
void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
if (FLAG_precompilation) {
InstanceCallNoopt(instr);
return;
}
if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
return;
}
@ -3070,10 +2979,6 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
break;
}
if (unary_kind != MathUnaryInstr::kIllegal) {
if (FLAG_precompilation) {
// TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well.
return;
}
MathUnaryInstr* math_unary =
new(Z) MathUnaryInstr(unary_kind,
new(Z) Value(call->ArgumentAt(0)),
@ -3156,10 +3061,6 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
case MethodRecognizer::kMathAcos:
case MethodRecognizer::kMathAtan:
case MethodRecognizer::kMathAtan2: {
if (FLAG_precompilation) {
// No UnboxDouble instructons allowed.
return;
}
// InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble
// instructions contain type checks and conversions to double.
ZoneGrowableArray<Value*>* args =

View file

@ -30,10 +30,6 @@ class FlowGraphOptimizer : public FlowGraphVisitor {
FlowGraph* flow_graph() const { return flow_graph_; }
// Add ICData to InstanceCalls, so that optimizations can be run on them.
// TODO(srdjan): StaticCals as well?
void PopulateWithICData();
// Use ICData to optimize, replace or eliminate instructions.
void ApplyICData();

View file

@ -15,8 +15,6 @@ DEFINE_FLAG(bool, trace_type_propagation, false,
"Trace flow graph type propagation");
DECLARE_FLAG(bool, propagate_types);
DECLARE_FLAG(bool, trace_cha);
DECLARE_FLAG(bool, use_cha_deopt);
DECLARE_FLAG(bool, fields_may_be_reset);

View file

@ -42,7 +42,6 @@ DEFINE_FLAG(bool, unbox_numeric_fields, true,
DEFINE_FLAG(bool, fields_may_be_reset, false,
"Don't optimize away static field initialization");
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, trace_optimization);
Definition::Definition(intptr_t deopt_id)
: Instruction(deopt_id),

View file

@ -55,10 +55,8 @@ DEFINE_FLAG(bool, overlap_type_arguments, true,
DEFINE_FLAG(bool, show_internal_names, false,
"Show names of internal classes (e.g. \"OneByteString\") in error messages "
"instead of showing the corresponding interface names (e.g. \"String\")");
DEFINE_FLAG(bool, trace_cha, false, "Trace CHA operations");
DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
DEFINE_FLAG(bool, ignore_patch_signature_mismatch, false,
"Ignore patch file member signature mismatch.");

View file

@ -53,7 +53,6 @@ DEFINE_FLAG(bool, warn_super, false,
DEFINE_FLAG(bool, await_is_keyword, false,
"await and yield are treated as proper keywords in synchronous code.");
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, profile_vm);

View file

@ -4,6 +4,7 @@
#include "vm/precompiler.h"
#include "vm/aot_optimizer.h"
#include "vm/assembler.h"
#include "vm/ast_printer.h"
#include "vm/branch_optimizer.h"
@ -21,7 +22,6 @@
#include "vm/flow_graph_builder.h"
#include "vm/flow_graph_compiler.h"
#include "vm/flow_graph_inliner.h"
#include "vm/flow_graph_optimizer.h"
#include "vm/flow_graph_range_analysis.h"
#include "vm/flow_graph_type_propagator.h"
#include "vm/hash_table.h"
@ -1027,33 +1027,6 @@ class NameFunctionsTraits {
typedef UnorderedHashMap<NameFunctionsTraits> Table;
class FunctionsTraits {
public:
static bool IsMatch(const Object& a, const Object& b) {
Zone* zone = Thread::Current()->zone();
String& a_s = String::Handle(zone);
String& b_s = String::Handle(zone);
a_s = a.IsFunction() ? Function::Cast(a).name() : String::Cast(a).raw();
b_s = b.IsFunction() ? Function::Cast(b).name() : String::Cast(b).raw();
ASSERT(a_s.IsSymbol() && b_s.IsSymbol());
return a_s.raw() == b_s.raw();
}
static uword Hash(const Object& obj) {
if (obj.IsFunction()) {
return String::Handle(Function::Cast(obj).name()).Hash();
} else {
ASSERT(String::Cast(obj).IsSymbol());
return String::Cast(obj).Hash();
}
}
static RawObject* NewKey(const Function& function) {
return function.raw();
}
};
typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
static void AddNameToFunctionsTable(Zone* zone,
Table* table,
const String& fname,
@ -2014,9 +1987,9 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
caller_inline_id.Add(-1);
CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer);
FlowGraphOptimizer optimizer(flow_graph,
use_speculative_inlining,
&inlining_black_list);
AotOptimizer optimizer(flow_graph,
use_speculative_inlining,
&inlining_black_list);
optimizer.PopulateWithICData();
optimizer.ApplyClassIds();

View file

@ -7,6 +7,7 @@
#include "vm/allocation.h"
#include "vm/hash_map.h"
#include "vm/hash_table.h"
#include "vm/object.h"
namespace dart {
@ -342,6 +343,34 @@ class Precompiler : public ValueObject {
Error& error_;
};
class FunctionsTraits {
public:
static bool IsMatch(const Object& a, const Object& b) {
Zone* zone = Thread::Current()->zone();
String& a_s = String::Handle(zone);
String& b_s = String::Handle(zone);
a_s = a.IsFunction() ? Function::Cast(a).name() : String::Cast(a).raw();
b_s = b.IsFunction() ? Function::Cast(b).name() : String::Cast(b).raw();
ASSERT(a_s.IsSymbol() && b_s.IsSymbol());
return a_s.raw() == b_s.raw();
}
static uword Hash(const Object& obj) {
if (obj.IsFunction()) {
return String::Handle(Function::Cast(obj).name()).Hash();
} else {
ASSERT(String::Cast(obj).IsSymbol());
return String::Cast(obj).Hash();
}
}
static RawObject* NewKey(const Function& function) {
return function.raw();
}
};
typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
} // namespace dart
#endif // VM_PRECOMPILER_H_

View file

@ -21,7 +21,6 @@ DEFINE_FLAG(bool, trace_load_optimization, false,
DECLARE_FLAG(bool, fields_may_be_reset);
DECLARE_FLAG(bool, precompilation);
DECLARE_FLAG(bool, trace_optimization);
// Quick access to the current zone.
#define Z (zone())

View file

@ -15,7 +15,6 @@
namespace dart {
DEFINE_FLAG(bool, trace_resolving, false, "Trace resolving.");
DECLARE_FLAG(bool, lazy_dispatchers);
// The actual names of named arguments are not checked by the dynamic resolver,
// but by the method entry code. It is important that the dynamic resolver

View file

@ -16,8 +16,6 @@
namespace dart {
DECLARE_FLAG(bool, lazy_dispatchers);
// Unit test for empty stack frame iteration.
VM_TEST_CASE(EmptyStackFrameIteration) {
StackFrameIterator iterator(StackFrameIterator::kValidateFrames);

View file

@ -27,7 +27,6 @@ DEFINE_FLAG(bool, use_slow_path, false,
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, lazy_dispatchers);
// Input parameters:
// LR : return address.

View file

@ -26,7 +26,6 @@ DEFINE_FLAG(bool, use_slow_path, false,
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, lazy_dispatchers);
// Input parameters:
// LR : return address.

View file

@ -28,7 +28,6 @@ DEFINE_FLAG(bool, use_slow_path, false,
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, lazy_dispatchers);
#define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))

View file

@ -26,7 +26,6 @@ DEFINE_FLAG(bool, use_slow_path, false,
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, lazy_dispatchers);
// Input parameters:
// RA : return address.

View file

@ -27,7 +27,6 @@ DEFINE_FLAG(bool, use_slow_path, false,
"Set to true for debugging & verifying the slow paths.");
DECLARE_FLAG(bool, trace_optimized_ic_calls);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, lazy_dispatchers);
// Input parameters:
// RSP : points to return address.

View file

@ -304,6 +304,32 @@
'..',
],
},
{
'target_name': 'libdart_lib_precompiled_runtime',
'type': 'static_library',
'toolsets':['host', 'target'],
'includes': [
'../lib/async_sources.gypi',
'../lib/collection_sources.gypi',
'../lib/core_sources.gypi',
'../lib/developer_sources.gypi',
'../lib/internal_sources.gypi',
'../lib/isolate_sources.gypi',
'../lib/math_sources.gypi',
'../lib/mirrors_sources.gypi',
'../lib/typed_data_sources.gypi',
'../lib/vmservice_sources.gypi',
],
'sources': [
'bootstrap_nocore.cc',
],
'defines': [
'DART_PRECOMPILED_RUNTIME',
],
'include_dirs': [
'..',
],
},
{
'target_name': 'generate_async_cc_file',
'type': 'none',

View file

@ -9,6 +9,8 @@
'allocation.cc',
'allocation.h',
'allocation_test.cc',
'aot_optimizer.cc',
'aot_optimizer.h',
'assembler.cc',
'assembler.h',
'assembler_arm.cc',