| Index: runtime/vm/jit_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/jit_optimizer.cc
|
| similarity index 90%
|
| rename from runtime/vm/flow_graph_optimizer.cc
|
| rename to runtime/vm/jit_optimizer.cc
|
| index fa5649ffc593681a88dd8072a9c0856f475ba8f7..35713268d58b967804ded7dcd21a8ad433fc0f0c 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/jit_optimizer.cc
|
| @@ -2,7 +2,7 @@
|
| // 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.
|
|
|
| -#include "vm/flow_graph_optimizer.h"
|
| +#include "vm/jit_optimizer.h"
|
|
|
| #include "vm/bit_vector.h"
|
| #include "vm/branch_optimizer.h"
|
| @@ -47,7 +47,7 @@ static bool CanConvertUnboxedMintToDouble() {
|
|
|
|
|
| // Optimize instance calls using ICData.
|
| -void FlowGraphOptimizer::ApplyICData() {
|
| +void JitOptimizer::ApplyICData() {
|
| VisitBlocks();
|
| }
|
|
|
| @@ -58,7 +58,7 @@ void FlowGraphOptimizer::ApplyICData() {
|
| // have no runtime type feedback collected.
|
| // Attempts to convert an instance call (IC call) using propagated class-ids,
|
| // e.g., receiver class id, guarded-cid, or by guessing cid-s.
|
| -void FlowGraphOptimizer::ApplyClassIds() {
|
| +void JitOptimizer::ApplyClassIds() {
|
| ASSERT(current_iterator_ == NULL);
|
| for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
|
| !block_it.Done();
|
| @@ -89,7 +89,7 @@ static bool IsNumberCid(intptr_t cid) {
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
| +bool JitOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| if (call->ic_data()->NumberOfUsedChecks() > 0) {
|
| // This occurs when an instance call has too many checks, will be converted
|
| @@ -198,8 +198,8 @@ bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) {
|
| }
|
|
|
|
|
| -const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data,
|
| - intptr_t cid) {
|
| +const ICData& JitOptimizer::TrySpecializeICData(const ICData& ic_data,
|
| + intptr_t cid) {
|
| ASSERT(ic_data.NumArgsTested() == 1);
|
|
|
| if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) {
|
| @@ -226,7 +226,7 @@ const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data,
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::SpecializePolymorphicInstanceCall(
|
| +void JitOptimizer::SpecializePolymorphicInstanceCall(
|
| PolymorphicInstanceCallInstr* call) {
|
| if (!FLAG_polymorphic_with_deopt) {
|
| // Specialization adds receiver checks which can lead to deoptimization.
|
| @@ -275,7 +275,7 @@ static bool IsPositiveOrZeroSmiConst(Definition* d) {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
|
| +void JitOptimizer::OptimizeLeftShiftBitAndSmiOp(
|
| Definition* bit_and_instr,
|
| Definition* left_instr,
|
| Definition* right_instr) {
|
| @@ -313,10 +313,10 @@ void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
|
| - intptr_t index,
|
| - Representation rep,
|
| - intptr_t cid) {
|
| +void JitOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
|
| + intptr_t index,
|
| + Representation rep,
|
| + intptr_t cid) {
|
| ExtractNthOutputInstr* extract =
|
| new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid);
|
| instr->ReplaceUsesWith(extract);
|
| @@ -341,7 +341,7 @@ void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
|
| // v7 <- +(v5, v6)
|
| // Because of the environment it is important that merged instruction replaces
|
| // first original instruction encountered.
|
| -void FlowGraphOptimizer::TryMergeTruncDivMod(
|
| +void JitOptimizer::TryMergeTruncDivMod(
|
| GrowableArray<BinarySmiOpInstr*>* merge_candidates) {
|
| if (merge_candidates->length() < 2) {
|
| // Need at least a TRUNCDIV and a MOD.
|
| @@ -402,7 +402,7 @@ void FlowGraphOptimizer::TryMergeTruncDivMod(
|
|
|
|
|
| // Tries to merge MathUnary operations, in this case sinus and cosinus.
|
| -void FlowGraphOptimizer::TryMergeMathUnary(
|
| +void JitOptimizer::TryMergeMathUnary(
|
| GrowableArray<MathUnaryInstr*>* merge_candidates) {
|
| if (!FlowGraphCompiler::SupportsSinCos() || !CanUnboxDouble() ||
|
| !FLAG_merge_sin_cos) {
|
| @@ -463,7 +463,7 @@ void FlowGraphOptimizer::TryMergeMathUnary(
|
| // 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.
|
| // Merging occurs only per basic-block.
|
| -void FlowGraphOptimizer::TryOptimizePatterns() {
|
| +void JitOptimizer::TryOptimizePatterns() {
|
| if (!FLAG_truncating_left_shift) return;
|
| ASSERT(current_iterator_ == NULL);
|
| GrowableArray<BinarySmiOpInstr*> div_mod_merge;
|
| @@ -649,8 +649,8 @@ static bool ShouldSpecializeForDouble(const ICData& ic_data) {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::ReplaceCall(Definition* call,
|
| - Definition* replacement) {
|
| +void JitOptimizer::ReplaceCall(Definition* call,
|
| + Definition* replacement) {
|
| // Remove the original push arguments.
|
| for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
|
| PushArgumentInstr* push = call->PushArgumentAt(i);
|
| @@ -661,10 +661,10 @@ void FlowGraphOptimizer::ReplaceCall(Definition* call,
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::AddCheckSmi(Definition* to_check,
|
| - intptr_t deopt_id,
|
| - Environment* deopt_environment,
|
| - Instruction* insert_before) {
|
| +void JitOptimizer::AddCheckSmi(Definition* to_check,
|
| + intptr_t deopt_id,
|
| + Environment* deopt_environment,
|
| + Instruction* insert_before) {
|
| if (to_check->Type()->ToCid() != kSmiCid) {
|
| InsertBefore(insert_before,
|
| new(Z) CheckSmiInstr(new(Z) Value(to_check),
|
| @@ -676,10 +676,10 @@ void FlowGraphOptimizer::AddCheckSmi(Definition* to_check,
|
| }
|
|
|
|
|
| -Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check,
|
| - const ICData& unary_checks,
|
| - intptr_t deopt_id,
|
| - TokenPosition token_pos) {
|
| +Instruction* JitOptimizer::GetCheckClass(Definition* to_check,
|
| + const ICData& unary_checks,
|
| + intptr_t deopt_id,
|
| + TokenPosition token_pos) {
|
| if ((unary_checks.NumberOfUsedChecks() == 1) &&
|
| unary_checks.HasReceiverClassId(kSmiCid)) {
|
| return new(Z) CheckSmiInstr(new(Z) Value(to_check),
|
| @@ -691,11 +691,11 @@ Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check,
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::AddCheckClass(Definition* to_check,
|
| - const ICData& unary_checks,
|
| - intptr_t deopt_id,
|
| - Environment* deopt_environment,
|
| - Instruction* insert_before) {
|
| +void JitOptimizer::AddCheckClass(Definition* to_check,
|
| + const ICData& unary_checks,
|
| + intptr_t deopt_id,
|
| + Environment* deopt_environment,
|
| + Instruction* insert_before) {
|
| // Type propagation has not run yet, we cannot eliminate the check.
|
| Instruction* check = GetCheckClass(
|
| to_check, unary_checks, deopt_id, insert_before->token_pos());
|
| @@ -703,7 +703,7 @@ void FlowGraphOptimizer::AddCheckClass(Definition* to_check,
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::AddReceiverCheck(InstanceCallInstr* call) {
|
| +void JitOptimizer::AddReceiverCheck(InstanceCallInstr* call) {
|
| AddCheckClass(call->ArgumentAt(0),
|
| ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()),
|
| call->deopt_id(),
|
| @@ -729,7 +729,7 @@ static bool ArgIsAlways(intptr_t cid,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
|
| +bool JitOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
|
| // Check for monomorphic IC data.
|
| if (!call->HasICData()) return false;
|
| const ICData& ic_data =
|
| @@ -761,8 +761,8 @@ static bool IsLengthOneString(Definition* d) {
|
| // comparison. Conversion is only possible for strings of length one.
|
| // E.g., detect str[x] == "x"; and use an integer comparison of char-codes.
|
| // TODO(srdjan): Expand for two-byte and external strings.
|
| -bool FlowGraphOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| ASSERT(HasOnlyTwoOf(*call->ic_data(), kOneByteStringCid));
|
| // Check that left and right are length one strings (either string constants
|
| // or results of string-from-char-code.
|
| @@ -848,8 +848,8 @@ bool FlowGraphOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
|
|
|
| static bool SmiFitsInDouble() { return kSmiBits < 53; }
|
|
|
| -bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| const ICData& ic_data = *call->ic_data();
|
| ASSERT(ic_data.NumArgsTested() == 2);
|
|
|
| @@ -957,8 +957,8 @@ bool FlowGraphOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| const ICData& ic_data = *call->ic_data();
|
| ASSERT(ic_data.NumArgsTested() == 2);
|
|
|
| @@ -1019,8 +1019,8 @@ bool FlowGraphOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| intptr_t operands_type = kIllegalCid;
|
| ASSERT(call->HasICData());
|
| const ICData& ic_data = *call->ic_data();
|
| @@ -1228,8 +1228,8 @@ bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| ASSERT(call->ArgumentCount() == 1);
|
| Definition* input = call->ArgumentAt(0);
|
| Definition* unary_op = NULL;
|
| @@ -1263,8 +1263,8 @@ bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
|
|
|
|
|
| // Using field class
|
| -RawField* FlowGraphOptimizer::GetField(intptr_t class_id,
|
| - const String& field_name) {
|
| +RawField* JitOptimizer::GetField(intptr_t class_id,
|
| + const String& field_name) {
|
| Class& cls = Class::Handle(Z, isolate()->class_table()->At(class_id));
|
| Field& field = Field::Handle(Z);
|
| while (!cls.IsNull()) {
|
| @@ -1281,7 +1281,7 @@ RawField* FlowGraphOptimizer::GetField(intptr_t class_id,
|
| // Use CHA to determine if the call needs a class check: if the callee's
|
| // receiver is the same as the caller's receiver and there are no overriden
|
| // callee functions, then no class check is needed.
|
| -bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
|
| +bool JitOptimizer::InstanceCallNeedsClassCheck(
|
| InstanceCallInstr* call, RawFunction::Kind kind) const {
|
| if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) {
|
| // Even if class or function are private, lazy class finalization
|
| @@ -1312,8 +1312,7 @@ bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call,
|
| - bool allow_check) {
|
| +bool JitOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| const ICData& ic_data = *call->ic_data();
|
| ASSERT(ic_data.HasOneTarget());
|
| @@ -1328,9 +1327,6 @@ bool FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call,
|
| ASSERT(!field.IsNull());
|
|
|
| if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) {
|
| - if (!allow_check) {
|
| - return false;
|
| - }
|
| AddReceiverCheck(call);
|
| }
|
| LoadFieldInstr* load = new(Z) LoadFieldInstr(
|
| @@ -1363,8 +1359,8 @@ bool FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
|
| - MethodRecognizer::Kind getter) {
|
| +bool JitOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
|
| + MethodRecognizer::Kind getter) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1438,8 +1434,8 @@ bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
|
| - MethodRecognizer::Kind getter) {
|
| +bool JitOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
|
| + MethodRecognizer::Kind getter) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1464,8 +1460,8 @@ bool FlowGraphOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
|
| - MethodRecognizer::Kind getter) {
|
| +bool JitOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
|
| + MethodRecognizer::Kind getter) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1539,8 +1535,8 @@ bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1572,8 +1568,8 @@ bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1604,8 +1600,8 @@ bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
| - Token::Kind op_kind) {
|
| +bool JitOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
| + Token::Kind op_kind) {
|
| if (!ShouldInlineSimd()) {
|
| return false;
|
| }
|
| @@ -1637,9 +1633,7 @@ bool FlowGraphOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
|
|
|
|
|
| // Only unique implicit instance getters can be currently handled.
|
| -// Returns false if 'allow_check' is false and a check is needed.
|
| -bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call,
|
| - bool allow_check) {
|
| +bool JitOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| const ICData& ic_data = *call->ic_data();
|
| if (ic_data.NumberOfUsedChecks() == 0) {
|
| @@ -1659,11 +1653,11 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call,
|
| // inlining in FlowGraphInliner.
|
| return false;
|
| }
|
| - return InlineImplicitInstanceGetter(call, allow_check);
|
| + return InlineImplicitInstanceGetter(call);
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline(
|
| +bool JitOptimizer::TryReplaceInstanceCallWithInline(
|
| InstanceCallInstr* call) {
|
| Function& target = Function::Handle(Z);
|
| GrowableArray<intptr_t> class_ids;
|
| @@ -1707,7 +1701,7 @@ bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline(
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::ReplaceWithMathCFunction(
|
| +void JitOptimizer::ReplaceWithMathCFunction(
|
| InstanceCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| AddReceiverCheck(call);
|
| @@ -1748,7 +1742,7 @@ static bool IsSupportedByteArrayViewCid(intptr_t cid) {
|
|
|
|
|
| // Inline only simple, frequently called core library methods.
|
| -bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| +bool JitOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| ASSERT(call->HasICData());
|
| const ICData& ic_data = *call->ic_data();
|
| if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) {
|
| @@ -1981,7 +1975,7 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
|
| +bool JitOptimizer::TryInlineFloat32x4Constructor(
|
| StaticCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2024,7 +2018,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
|
| +bool JitOptimizer::TryInlineFloat64x2Constructor(
|
| StaticCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2059,7 +2053,7 @@ bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineInt32x4Constructor(
|
| +bool JitOptimizer::TryInlineInt32x4Constructor(
|
| StaticCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2096,7 +2090,7 @@ bool FlowGraphOptimizer::TryInlineInt32x4Constructor(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineFloat32x4Method(
|
| +bool JitOptimizer::TryInlineFloat32x4Method(
|
| InstanceCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2260,7 +2254,7 @@ bool FlowGraphOptimizer::TryInlineFloat32x4Method(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineFloat64x2Method(
|
| +bool JitOptimizer::TryInlineFloat64x2Method(
|
| InstanceCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2319,7 +2313,7 @@ bool FlowGraphOptimizer::TryInlineFloat64x2Method(
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineInt32x4Method(
|
| +bool JitOptimizer::TryInlineInt32x4Method(
|
| InstanceCallInstr* call,
|
| MethodRecognizer::Kind recognized_kind) {
|
| if (!ShouldInlineSimd()) {
|
| @@ -2390,7 +2384,7 @@ bool FlowGraphOptimizer::TryInlineInt32x4Method(
|
| // If no mapping is possible, 'results' is empty.
|
| // An instance-of test returning all same results can be converted to a class
|
| // check.
|
| -RawBool* FlowGraphOptimizer::InstanceOfAsBool(
|
| +RawBool* JitOptimizer::InstanceOfAsBool(
|
| const ICData& ic_data,
|
| const AbstractType& type,
|
| ZoneGrowableArray<intptr_t>* results) const {
|
| @@ -2449,7 +2443,7 @@ RawBool* FlowGraphOptimizer::InstanceOfAsBool(
|
|
|
|
|
| // Returns true if checking against this type is a direct class id comparison.
|
| -bool FlowGraphOptimizer::TypeCheckAsClassEquality(const AbstractType& type) {
|
| +bool JitOptimizer::TypeCheckAsClassEquality(const AbstractType& type) {
|
| ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
|
| // Requires CHA.
|
| if (!type.IsInstantiated()) return false;
|
| @@ -2553,7 +2547,7 @@ static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results,
|
|
|
|
|
| // TODO(srdjan): Use ICData to check if always true or false.
|
| -void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
| +void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
| ASSERT(Token::IsTypeTestOperator(call->token_kind()));
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* type_args = NULL;
|
| @@ -2661,7 +2655,7 @@ void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
|
|
|
|
|
| // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
|
| -void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
| +void JitOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
| ASSERT(Token::IsTypeCastOperator(call->token_kind()));
|
| Definition* left = call->ArgumentAt(0);
|
| Definition* type_args = call->ArgumentAt(1);
|
| @@ -2704,154 +2698,9 @@ void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::IsBlackListedForInlining(intptr_t call_deopt_id) {
|
| - for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
|
| - if ((*inlining_black_list_)[i] == call_deopt_id) return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -// Special optimizations when running in --noopt mode.
|
| -void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) {
|
| - // TODO(srdjan): Investigate other attempts, as they are not allowed to
|
| - // deoptimize.
|
| -
|
| - // Type test is special as it always gets converted into inlined code.
|
| - const Token::Kind op_kind = instr->token_kind();
|
| - if (Token::IsTypeTestOperator(op_kind)) {
|
| - ReplaceWithInstanceOf(instr);
|
| - return;
|
| - }
|
| - if (Token::IsTypeCastOperator(op_kind)) {
|
| - ReplaceWithTypeCast(instr);
|
| - return;
|
| - }
|
| -
|
| - if ((op_kind == Token::kGET) &&
|
| - TryInlineInstanceGetter(instr, false /* no checks allowed */)) {
|
| - return;
|
| - }
|
| - const ICData& unary_checks =
|
| - ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
|
| - if ((unary_checks.NumberOfChecks() > 0) &&
|
| - (op_kind == Token::kSET) &&
|
| - TryInlineInstanceSetter(instr, unary_checks, false /* no checks */)) {
|
| - return;
|
| - }
|
| -
|
| - if (use_speculative_inlining_ &&
|
| - !IsBlackListedForInlining(instr->deopt_id()) &&
|
| - (unary_checks.NumberOfChecks() > 0)) {
|
| - if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
|
| - return;
|
| - }
|
| - if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
|
| - return;
|
| - }
|
| - if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) {
|
| - return;
|
| - }
|
| -
|
| - if (Token::IsRelationalOperator(op_kind) &&
|
| - TryReplaceWithRelationalOp(instr, op_kind)) {
|
| - return;
|
| - }
|
| -
|
| - if (Token::IsBinaryOperator(op_kind) &&
|
| - TryReplaceWithBinaryOp(instr, op_kind)) {
|
| - return;
|
| - }
|
| - if (Token::IsUnaryOperator(op_kind) &&
|
| - TryReplaceWithUnaryOp(instr, op_kind)) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - bool has_one_target =
|
| - (unary_checks.NumberOfChecks() > 0) && unary_checks.HasOneTarget();
|
| - if (has_one_target) {
|
| - // Check if the single target is a polymorphic target, if it is,
|
| - // we don't have one target.
|
| - const Function& target =
|
| - Function::Handle(Z, unary_checks.GetTargetAt(0));
|
| - const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target);
|
| - has_one_target = !polymorphic_target;
|
| - }
|
| -
|
| - if (has_one_target) {
|
| - RawFunction::Kind function_kind =
|
| - Function::Handle(Z, unary_checks.GetTargetAt(0)).kind();
|
| - if (!InstanceCallNeedsClassCheck(instr, function_kind)) {
|
| - PolymorphicInstanceCallInstr* call =
|
| - new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
|
| - /* with_checks = */ false);
|
| - instr->ReplaceWith(call, current_iterator());
|
| - return;
|
| - }
|
| - }
|
| -
|
| - // More than one targets. Generate generic polymorphic call without
|
| - // deoptimization.
|
| - if (instr->ic_data()->NumberOfUsedChecks() > 0) {
|
| - ASSERT(!FLAG_polymorphic_with_deopt);
|
| - // OK to use checks with PolymorphicInstanceCallInstr since no
|
| - // deoptimization is allowed.
|
| - PolymorphicInstanceCallInstr* call =
|
| - new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
|
| - /* with_checks = */ true);
|
| - instr->ReplaceWith(call, current_iterator());
|
| - return;
|
| - }
|
| -
|
| - // No IC data checks. Try resolve target using the propagated type.
|
| - // If the propagated type has a method with the target name and there are
|
| - // no overrides with that name according to CHA, call the method directly.
|
| - const intptr_t receiver_cid =
|
| - instr->PushArgumentAt(0)->value()->Type()->ToCid();
|
| - if (receiver_cid == kDynamicCid) return;
|
| - const Class& receiver_class = Class::Handle(Z,
|
| - isolate()->class_table()->At(receiver_cid));
|
| -
|
| - const Array& args_desc_array = Array::Handle(Z,
|
| - ArgumentsDescriptor::New(instr->ArgumentCount(),
|
| - instr->argument_names()));
|
| - ArgumentsDescriptor args_desc(args_desc_array);
|
| - const Function& function = Function::Handle(Z,
|
| - Resolver::ResolveDynamicForReceiverClass(
|
| - receiver_class,
|
| - instr->function_name(),
|
| - args_desc));
|
| - if (function.IsNull()) {
|
| - return;
|
| - }
|
| - if (!thread()->cha()->HasOverride(receiver_class, instr->function_name())) {
|
| - if (FLAG_trace_cha) {
|
| - THR_Print(" **(CHA) Instance call needs no check, "
|
| - "no overrides of '%s' '%s'\n",
|
| - instr->function_name().ToCString(), receiver_class.ToCString());
|
| - }
|
| - thread()->cha()->AddToLeafClasses(receiver_class);
|
| -
|
| - // Create fake IC data with the resolved target.
|
| - const ICData& ic_data = ICData::Handle(
|
| - ICData::New(flow_graph_->function(),
|
| - instr->function_name(),
|
| - args_desc_array,
|
| - Thread::kNoDeoptId,
|
| - /* args_tested = */ 1));
|
| - ic_data.AddReceiverCheck(receiver_class.id(), function);
|
| - PolymorphicInstanceCallInstr* call =
|
| - new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
|
| - /* with_checks = */ false);
|
| - instr->ReplaceWith(call, current_iterator());
|
| - return;
|
| - }
|
| -}
|
| -
|
| -
|
| // Tries to optimize instance call by replacing it with a faster instruction
|
| // (e.g, binary op, field load, ..).
|
| -void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
| +void JitOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
| if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
|
| return;
|
| }
|
| @@ -2957,7 +2806,7 @@ void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
| +void JitOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
| if (!CanUnboxDouble()) {
|
| return;
|
| }
|
| @@ -3130,7 +2979,7 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::VisitStoreInstanceField(
|
| +void JitOptimizer::VisitStoreInstanceField(
|
| StoreInstanceFieldInstr* instr) {
|
| if (instr->IsUnboxedStore()) {
|
| ASSERT(instr->is_potential_unboxed_initialization_);
|
| @@ -3184,7 +3033,7 @@ void FlowGraphOptimizer::VisitStoreInstanceField(
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::VisitAllocateContext(AllocateContextInstr* instr) {
|
| +void JitOptimizer::VisitAllocateContext(AllocateContextInstr* instr) {
|
| // Replace generic allocation with a sequence of inlined allocation and
|
| // explicit initalizing stores.
|
| AllocateUninitializedContextInstr* replacement =
|
| @@ -3219,7 +3068,7 @@ void FlowGraphOptimizer::VisitAllocateContext(AllocateContextInstr* instr) {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
|
| +void JitOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
|
| // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
|
| #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
|
| if (!instr->can_pack_into_smi())
|
| @@ -3228,9 +3077,8 @@ void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
|
| }
|
|
|
|
|
| -bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
| - const ICData& unary_ic_data,
|
| - bool allow_checks) {
|
| +bool JitOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
| + const ICData& unary_ic_data) {
|
| ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
|
| (unary_ic_data.NumArgsTested() == 1));
|
| if (I->flags().type_checks()) {
|
| @@ -3264,15 +3112,9 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
| ASSERT(!field.IsNull());
|
|
|
| if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) {
|
| - if (!allow_checks) {
|
| - return false;
|
| - }
|
| AddReceiverCheck(instr);
|
| }
|
| if (field.guarded_cid() != kDynamicCid) {
|
| - if (!allow_checks) {
|
| - return false;
|
| - }
|
| InsertBefore(instr,
|
| new(Z) GuardFieldClassInstr(
|
| new(Z) Value(instr->ArgumentAt(1)),
|
| @@ -3283,9 +3125,6 @@ bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
| }
|
|
|
| if (field.needs_length_check()) {
|
| - if (!allow_checks) {
|
| - return false;
|
| - }
|
| InsertBefore(instr,
|
| new(Z) GuardFieldLengthInstr(
|
| new(Z) Value(instr->ArgumentAt(1)),
|
|
|