From dd2d040ccb2608e4e320cdb8bdd7a410afb5ade6 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Fri, 8 May 2020 15:53:09 +0000 Subject: [PATCH] [vm] Cleanup flags which disable argument type checks and strong mode types The following options are removed: --use_strong_mode_types --experimental_unsafe_mode_use_at_your_own_risk The following flags and predicates are removed: Dart_IsolateFlags::unsafe_trust_strong_mode_types Isolate::argument_type_checks() Isolate::can_use_strong_mode_types() Isolate::should_emit_strong_mode_checks() Also, everything depending on these flags is cleaned up. Change-Id: I9328009ad5a42ea2173842386d612c465e3ebec1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147325 Reviewed-by: Martin Kustermann Commit-Queue: Alexander Markov --- runtime/include/dart_api.h | 3 +- .../vm/compiler/aot/aot_call_specializer.cc | 45 +--- runtime/vm/compiler/backend/flow_graph.cc | 6 +- .../compiler/backend/flow_graph_compiler.cc | 20 +- .../vm/compiler/backend/flow_graph_compiler.h | 1 - .../backend/flow_graph_compiler_arm.cc | 14 -- .../backend/flow_graph_compiler_arm64.cc | 13 -- .../backend/flow_graph_compiler_ia32.cc | 15 -- .../backend/flow_graph_compiler_x64.cc | 13 -- runtime/vm/compiler/backend/il.cc | 3 +- runtime/vm/compiler/backend/inliner.cc | 105 ++------- .../vm/compiler/backend/type_propagator.cc | 212 ++++++++---------- runtime/vm/compiler/call_specializer.cc | 10 +- .../frontend/base_flow_graph_builder.cc | 7 - .../frontend/bytecode_flow_graph_builder.cc | 2 +- .../vm/compiler/frontend/bytecode_reader.cc | 2 +- .../frontend/bytecode_scope_builder.cc | 3 +- .../frontend/kernel_binary_flowgraph.cc | 9 +- runtime/vm/compiler/frontend/kernel_to_il.cc | 16 +- runtime/vm/compiler/frontend/scope_builder.cc | 2 +- runtime/vm/compiler/graph_intrinsifier.cc | 16 -- runtime/vm/compiler/recognized_methods_list.h | 4 +- runtime/vm/flag_list.h | 4 - runtime/vm/isolate.h | 20 +- runtime/vm/kernel_isolate.cc | 1 - runtime/vm/object.cc | 4 +- runtime/vm/object.h | 7 +- runtime/vm/scopes.h | 5 +- 28 files changed, 135 insertions(+), 427 deletions(-) diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 51bb6169bde..f0951dbeb71 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -518,7 +518,7 @@ typedef struct { * for each part. */ -#define DART_FLAGS_CURRENT_VERSION (0x0000000b) +#define DART_FLAGS_CURRENT_VERSION (0x0000000c) typedef struct { int32_t version; @@ -528,7 +528,6 @@ typedef struct { bool obfuscate; Dart_QualifiedFunctionName* entry_points; bool load_vmservice_library; - bool unsafe_trust_strong_mode_types; bool copy_parent_code; } Dart_IsolateFlags; diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc index 4da0354c87c..316cbd06730 100644 --- a/runtime/vm/compiler/aot/aot_call_specializer.cc +++ b/runtime/vm/compiler/aot/aot_call_specializer.cc @@ -294,7 +294,6 @@ bool AotCallSpecializer::IsSupportedIntOperandForStaticDoubleOp( Value* AotCallSpecializer::PrepareStaticOpInput(Value* input, intptr_t cid, Instruction* call) { - ASSERT(I->can_use_strong_mode_types()); ASSERT((cid == kDoubleCid) || (cid == kMintCid)); if (input->Type()->is_nullable()) { @@ -368,18 +367,13 @@ static void RefineUseTypes(Definition* instr) { bool AotCallSpecializer::TryOptimizeInstanceCallUsingStaticTypes( InstanceCallInstr* instr) { - ASSERT(I->can_use_strong_mode_types()); - const Token::Kind op_kind = instr->token_kind(); - return TryOptimizeIntegerOperation(instr, op_kind) || TryOptimizeDoubleOperation(instr, op_kind); } bool AotCallSpecializer::TryOptimizeStaticCallUsingStaticTypes( StaticCallInstr* instr) { - ASSERT(I->can_use_strong_mode_types()); - const String& name = String::Handle(Z, instr->function().name()); const Token::Kind op_kind = MethodTokenRecognizer::RecognizeTokenKind(name); @@ -472,8 +466,6 @@ bool AotCallSpecializer::TryOptimizeIntegerOperation(TemplateDartCall<0>* instr, return false; } - ASSERT(I->can_use_strong_mode_types()); - Definition* replacement = NULL; if (instr->ArgumentCount() == 2) { Value* left_value = instr->ArgumentValueAt(0); @@ -801,43 +793,8 @@ void AotCallSpecializer::VisitInstanceCall(InstanceCallInstr* instr) { const CallTargets& targets = instr->Targets(); const intptr_t receiver_idx = instr->FirstArgIndex(); - if (I->can_use_strong_mode_types()) { - // In AOT strong mode, we avoid deopting speculation. - // TODO(ajcbik): replace this with actual analysis phase - // that determines if checks are removed later. - } else if (speculative_policy_->IsAllowedForInlining(instr->deopt_id()) && - !targets.is_empty()) { - 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; - } - - if (TryInlineInstanceMethod(instr)) { - return; - } - } - - if (I->can_use_strong_mode_types() && - TryOptimizeInstanceCallUsingStaticTypes(instr)) { + if (TryOptimizeInstanceCallUsingStaticTypes(instr)) { return; } diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc index c930e71c16e..6c7297f3b6b 100644 --- a/runtime/vm/compiler/backend/flow_graph.cc +++ b/runtime/vm/compiler/backend/flow_graph.cc @@ -424,8 +424,8 @@ FlowGraph::ToCheck FlowGraph::CheckForInstanceCall( if (function().IsDynamicFunction() && IsReceiver(receiver->definition())) { // Call receiver is callee receiver: calling "this.g()" in f(). receiver_class = function().Owner(); - } else if (isolate()->can_use_strong_mode_types()) { - // In strong mode, get the receiver's compile type. Note that + } else { + // Get the receiver's compile type. Note that // we allow nullable types, which may result in just generating // a null check rather than the more elaborate class check CompileType* type = receiver->Type(); @@ -1381,7 +1381,7 @@ void FlowGraph::RenameRecursive( captured_parameters_->Add(index); } - if ((phi != NULL) && isolate()->can_use_strong_mode_types()) { + if (phi != nullptr) { // Assign type to Phi if it doesn't have a type yet. // For a Phi to appear in the local variable it either was placed // there as incoming value by renaming or it was stored there by diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc index a00b77c26dd..60cbfb7a6ef 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc @@ -1309,26 +1309,8 @@ bool FlowGraphCompiler::TryIntrinsifyHelper() { } return false; } - case FunctionLayout::kImplicitSetter: { - if (!isolate()->argument_type_checks()) { - Field& field = Field::Handle(function().accessor_field()); - ASSERT(!field.IsNull()); -#if defined(DEBUG) - // HACK: Clone the field to ignore assertion in Field::guarded_cid(). - // The same reasons as above apply, but we only check if it's dynamic. - field = field.CloneFromOriginal(); -#endif - - if (field.is_instance() && field.guarded_cid() == kDynamicCid) { - SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics); - GenerateSetterIntrinsic(compiler::target::Field::OffsetOf(field)); - SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics); - return true; - } - return false; - } + case FunctionLayout::kImplicitSetter: break; - } #if !defined(TARGET_ARCH_IA32) case FunctionLayout::kMethodExtractor: { auto& extracted_method = Function::ZoneHandle( diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h index 62a91c6e012..1635fc11eef 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler.h +++ b/runtime/vm/compiler/backend/flow_graph_compiler.h @@ -1094,7 +1094,6 @@ class FlowGraphCompiler : public ValueObject { intptr_t type_arguments_field_offset); void GenerateGetterIntrinsic(intptr_t offset); - void GenerateSetterIntrinsic(intptr_t offset); // Perform a greedy local register allocation. Consider all registers free. void AllocateRegistersLocally(Instruction* instr); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc index 58b1ee17365..c1349abe71b 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc @@ -871,20 +871,6 @@ void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) { __ Ret(); } -void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) { - // LR: return address. - // SP+1: receiver. - // SP+0: value. - // Sequence node has one store node and one return NULL node. - __ Comment("Intrinsic Setter"); - __ ldr(R0, - compiler::Address(SP, 1 * compiler::target::kWordSize)); // Receiver. - __ ldr(R1, compiler::Address(SP, 0 * compiler::target::kWordSize)); // Value. - __ StoreIntoObjectOffset(R0, offset, R1); - __ LoadObject(R0, Object::null_object()); - __ Ret(); -} - void FlowGraphCompiler::EmitFrameEntry() { const Function& function = parsed_function().function(); if (CanOptimizeFunction() && function.IsOptimizable() && diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc index 60bad9af9eb..a7bbc2eba52 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc @@ -832,19 +832,6 @@ void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) { __ ret(); } -void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) { - // LR: return address. - // SP+1: receiver. - // SP+0: value. - // Sequence node has one store node and one return NULL node. - __ Comment("Intrinsic Setter"); - __ LoadFromOffset(R0, SP, 1 * kWordSize); // Receiver. - __ LoadFromOffset(R1, SP, 0 * kWordSize); // Value. - __ StoreIntoObjectOffset(R0, offset, R1); - __ LoadObject(R0, Object::null_object()); - __ ret(); -} - void FlowGraphCompiler::EmitFrameEntry() { const Function& function = parsed_function().function(); if (CanOptimizeFunction() && function.IsOptimizable() && diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc index 9fbb02cb77d..9a69432c58c 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc @@ -752,21 +752,6 @@ void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) { __ ret(); } -void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) { - // TOS: return address. - // +1 : value - // +2 : receiver. - // Sequence node has one store node and one return NULL node. - __ Comment("Intrinsic Setter"); - __ movl(EAX, compiler::Address(ESP, 2 * kWordSize)); // Receiver. - __ movl(EBX, compiler::Address(ESP, 1 * kWordSize)); // Value. - __ StoreIntoObject(EAX, compiler::FieldAddress(EAX, offset), EBX); - const compiler::Immediate& raw_null = - compiler::Immediate(static_cast(Object::null())); - __ movl(EAX, raw_null); - __ ret(); -} - // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc // needs to be updated to match. void FlowGraphCompiler::EmitFrameEntry() { diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc index 091b51ffc6a..b8c8ba71ff8 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc @@ -837,19 +837,6 @@ void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) { __ ret(); } -void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) { - // TOS: return address. - // +1 : value - // +2 : receiver. - // Sequence node has one store node and one return NULL node. - __ Comment("Intrinsic Setter"); - __ movq(RAX, compiler::Address(RSP, 2 * kWordSize)); // Receiver. - __ movq(RBX, compiler::Address(RSP, 1 * kWordSize)); // Value. - __ StoreIntoObject(RAX, compiler::FieldAddress(RAX, offset), RBX); - __ LoadObject(RAX, Object::null_object()); - __ ret(); -} - // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc // needs to be updated to match. void FlowGraphCompiler::EmitFrameEntry() { diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index a37b4ef115c..ebd5cc6d362 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -2337,8 +2337,7 @@ Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) { if ((left_type->ToCid() == kSmiCid) && (right_type->ToCid() == kSmiCid)) { op_cid = kSmiCid; - } else if (Isolate::Current()->can_use_strong_mode_types() && - FlowGraphCompiler::SupportsUnboxedInt64() && + } else if (FlowGraphCompiler::SupportsUnboxedInt64() && // TODO(dartbug.com/30480): handle nullable types here left_type->IsNullableInt() && !left_type->is_nullable() && right_type->IsNullableInt() && !right_type->is_nullable()) { diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc index 169d57d3991..24ad6a3f30d 100644 --- a/runtime/vm/compiler/backend/inliner.cc +++ b/runtime/vm/compiler/backend/inliner.cc @@ -2535,7 +2535,7 @@ static bool InlineSetIndexed(FlowGraph* flow_graph, } Instruction* cursor = *entry; - if (flow_graph->isolate()->argument_type_checks() && !is_unchecked_call && + if (!is_unchecked_call && (kind != MethodRecognizer::kObjectArraySetIndexedUnchecked && kind != MethodRecognizer::kGrowableArraySetIndexedUnchecked)) { // Only type check for the value. A type check for the index is not @@ -2827,60 +2827,6 @@ static bool InlineLoadClassId(FlowGraph* flow_graph, return true; } -// Adds an explicit bounds check for a typed getter/setter. -static void PrepareInlineTypedArrayBoundsCheck(FlowGraph* flow_graph, - Instruction* call, - intptr_t array_cid, - intptr_t view_cid, - Definition* array, - Definition** byte_index, - Instruction** cursor) { - ASSERT(array_cid != kDynamicCid); - - LoadFieldInstr* length = new (Z) LoadFieldInstr( - new (Z) Value(array), Slot::GetLengthFieldForArrayCid(array_cid), - call->token_pos()); - *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue); - - intptr_t element_size = compiler::target::Instance::ElementSizeFor(array_cid); - ConstantInstr* bytes_per_element = - flow_graph->GetConstant(Smi::Handle(Z, Smi::New(element_size))); - BinarySmiOpInstr* len_in_bytes = new (Z) - BinarySmiOpInstr(Token::kMUL, new (Z) Value(length), - new (Z) Value(bytes_per_element), call->deopt_id()); - *cursor = flow_graph->AppendTo(*cursor, len_in_bytes, call->env(), - FlowGraph::kValue); - - // adjusted_length = len_in_bytes - (element_size - 1). - Definition* adjusted_length = len_in_bytes; - intptr_t adjustment = - compiler::target::Instance::ElementSizeFor(view_cid) - 1; - if (adjustment > 0) { - ConstantInstr* length_adjustment = - flow_graph->GetConstant(Smi::Handle(Z, Smi::New(adjustment))); - adjusted_length = new (Z) - BinarySmiOpInstr(Token::kSUB, new (Z) Value(len_in_bytes), - new (Z) Value(length_adjustment), call->deopt_id()); - *cursor = flow_graph->AppendTo(*cursor, adjusted_length, call->env(), - FlowGraph::kValue); - } - - // Check adjusted_length > 0. - // TODO(ajcbik): this is a synthetic check that cannot - // be directly linked to a use, is that a sign of wrong use? - ConstantInstr* zero = flow_graph->GetConstant(Object::smi_zero()); - Definition* check = - flow_graph->CreateCheckBound(adjusted_length, zero, call->deopt_id()); - *cursor = - flow_graph->AppendTo(*cursor, check, call->env(), FlowGraph::kValue); - - // Check 0 <= byte_index < adjusted_length. - *byte_index = flow_graph->CreateCheckBound(adjusted_length, *byte_index, - call->deopt_id()); - *cursor = flow_graph->AppendTo(*cursor, *byte_index, call->env(), - FlowGraph::kValue); -} - // Emits preparatory code for a typed getter/setter. // Handles three cases: // (1) dynamic: generates load untagged (internal or external) @@ -2919,12 +2865,12 @@ static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, // Dynamic calls are polymorphic due to: // (A) extra bounds check computations (length stored in receiver), // (B) external/internal typed data in receiver. - // For Dart2, both issues are resolved in the inlined code. + // Both issues are resolved in the inlined code. + // All getters that go through InlineByteArrayBaseLoad() have explicit + // bounds checks in all their clients in the library, so we can omit yet + // another inlined bounds check. if (array_cid == kDynamicCid) { ASSERT(call->IsStaticCall()); - if (!flow_graph->isolate()->can_use_strong_mode_types()) { - return false; - } } Definition* array = receiver; @@ -2935,15 +2881,6 @@ static bool InlineByteArrayBaseLoad(FlowGraph* flow_graph, (*entry)->InheritDeoptTarget(Z, call); Instruction* cursor = *entry; - // All getters that go through InlineByteArrayBaseLoad() have explicit - // bounds checks in all their clients in the library, so we can omit yet - // another inlined bounds check when compiling for Dart2 (resolves (A)). - const bool needs_bounds_check = - !flow_graph->isolate()->can_use_strong_mode_types(); - if (needs_bounds_check) { - PrepareInlineTypedArrayBoundsCheck(flow_graph, call, array_cid, view_cid, - array, &index, &cursor); - } // Generates a template for the load, either a dynamic conditional // that dispatches on external and internal storage, or a single @@ -2999,12 +2936,12 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, // Dynamic calls are polymorphic due to: // (A) extra bounds check computations (length stored in receiver), // (B) external/internal typed data in receiver. - // For Dart2, both issues are resolved in the inlined code. + // Both issues are resolved in the inlined code. + // All setters that go through InlineByteArrayBaseLoad() have explicit + // bounds checks in all their clients in the library, so we can omit yet + // another inlined bounds check. if (array_cid == kDynamicCid) { ASSERT(call->IsStaticCall()); - if (!flow_graph->isolate()->can_use_strong_mode_types()) { - return false; - } } Definition* array = receiver; @@ -3015,16 +2952,6 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, (*entry)->InheritDeoptTarget(Z, call); Instruction* cursor = *entry; - // All setters that go through InlineByteArrayBaseLoad() have explicit - // bounds checks in all their clients in the library, so we can omit yet - // another inlined bounds check when compiling for Dart2 (resolves (A)). - const bool needs_bounds_check = - !flow_graph->isolate()->can_use_strong_mode_types(); - if (needs_bounds_check) { - PrepareInlineTypedArrayBoundsCheck(flow_graph, call, array_cid, view_cid, - array, &index, &cursor); - } - // Prepare additional checks. In AOT Dart2, we use an explicit null check and // non-speculative unboxing for most value types. Cids* value_check = nullptr; @@ -3037,8 +2964,7 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, case kExternalTypedDataUint8ClampedArrayCid: case kTypedDataInt16ArrayCid: case kTypedDataUint16ArrayCid: { - if (CompilerState::Current().is_aot() && - flow_graph->isolate()->can_use_strong_mode_types()) { + if (CompilerState::Current().is_aot()) { needs_null_check = true; } else { // Check that value is always smi. @@ -3048,8 +2974,7 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, } case kTypedDataInt32ArrayCid: case kTypedDataUint32ArrayCid: - if (CompilerState::Current().is_aot() && - flow_graph->isolate()->can_use_strong_mode_types()) { + if (CompilerState::Current().is_aot()) { needs_null_check = true; } else { // On 64-bit platforms assume that stored value is always a smi. @@ -3061,8 +2986,7 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, case kTypedDataFloat32ArrayCid: case kTypedDataFloat64ArrayCid: { // Check that value is always double. - if (CompilerState::Current().is_aot() && - flow_graph->isolate()->can_use_strong_mode_types()) { + if (CompilerState::Current().is_aot()) { needs_null_check = true; } else { value_check = Cids::CreateMonomorphic(Z, kDoubleCid); @@ -3082,10 +3006,9 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph, case kTypedDataInt64ArrayCid: case kTypedDataUint64ArrayCid: // StoreIndexedInstr takes unboxed int64, so value is - // checked when unboxing. In AOT Dart2, we use an + // checked when unboxing. In AOT, we use an // explicit null check and non-speculative unboxing. - needs_null_check = CompilerState::Current().is_aot() && - flow_graph->isolate()->can_use_strong_mode_types(); + needs_null_check = CompilerState::Current().is_aot(); break; default: // Array cids are already checked in the caller. diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc index 81d0f03d121..1f4c05ddb43 100644 --- a/runtime/vm/compiler/backend/type_propagator.cc +++ b/runtime/vm/compiler/backend/type_propagator.cc @@ -59,15 +59,13 @@ FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) types_.Add(NULL); } - if (Isolate::Current()->argument_type_checks()) { - asserts_ = new ZoneGrowableArray( - flow_graph->current_ssa_temp_index()); - for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { - asserts_->Add(NULL); - } - - collected_asserts_ = new ZoneGrowableArray(10); + asserts_ = new ZoneGrowableArray( + flow_graph->current_ssa_temp_index()); + for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { + asserts_->Add(NULL); } + + collected_asserts_ = new ZoneGrowableArray(10); } void FlowGraphTypePropagator::Propagate() { @@ -121,13 +119,7 @@ void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) { const intptr_t rollback_point = rollback_.length(); - // When having assertions enabled or when running in strong-mode the IR graphs - // can contain [AssertAssignableInstr]s and we therefore enable this - // optimization. - Isolate* isolate = Isolate::Current(); - if (isolate->argument_type_checks()) { - StrengthenAsserts(block); - } + StrengthenAsserts(block); block->Accept(this); @@ -1096,43 +1088,41 @@ CompileType ParameterInstr::ComputeType() const { const bool is_unchecked_entry_param = graph_entry->unchecked_entry() == block_; - if (Isolate::Current()->can_use_strong_mode_types()) { - LocalScope* scope = graph_entry->parsed_function().scope(); - // Note: in catch-blocks we have ParameterInstr for each local variable - // not only for normal parameters. - const LocalVariable* param = nullptr; - if (scope != nullptr && (index() < scope->num_variables())) { - param = scope->VariableAt(index()); - } else if (index() < function.NumParameters()) { - param = graph_entry->parsed_function().RawParameterVariable(index()); + LocalScope* scope = graph_entry->parsed_function().scope(); + // Note: in catch-blocks we have ParameterInstr for each local variable + // not only for normal parameters. + const LocalVariable* param = nullptr; + if (scope != nullptr && (index() < scope->num_variables())) { + param = scope->VariableAt(index()); + } else if (index() < function.NumParameters()) { + param = graph_entry->parsed_function().RawParameterVariable(index()); + } + if (param != nullptr) { + CompileType* inferred_type = NULL; + if (!block_->IsCatchBlockEntry()) { + inferred_type = param->parameter_type(); } - if (param != nullptr) { - CompileType* inferred_type = NULL; - if (!block_->IsCatchBlockEntry()) { - inferred_type = param->parameter_type(); - } - // Best bet: use inferred type if it is a concrete class or int. - if ((inferred_type != nullptr) && - ((inferred_type->ToNullableCid() != kDynamicCid) || - inferred_type->IsNullableInt())) { - TraceStrongModeType(this, inferred_type); - return *inferred_type; - } - // If parameter type was checked by caller, then use Dart type annotation, - // plus non-nullability from inferred type if known. - if (param->was_type_checked_by_caller() || - (is_unchecked_entry_param && - !param->is_explicit_covariant_parameter())) { - const bool is_nullable = - (inferred_type == NULL) || inferred_type->is_nullable(); - TraceStrongModeType(this, param->type()); - return CompileType::FromAbstractType(param->type(), is_nullable); - } - // Last resort: use inferred non-nullability. - if (inferred_type != NULL) { - TraceStrongModeType(this, inferred_type); - return *inferred_type; - } + // Best bet: use inferred type if it is a concrete class or int. + if ((inferred_type != nullptr) && + ((inferred_type->ToNullableCid() != kDynamicCid) || + inferred_type->IsNullableInt())) { + TraceStrongModeType(this, inferred_type); + return *inferred_type; + } + // If parameter type was checked by caller, then use Dart type annotation, + // plus non-nullability from inferred type if known. + if (param->was_type_checked_by_caller() || + (is_unchecked_entry_param && + !param->is_explicit_covariant_parameter())) { + const bool is_nullable = + (inferred_type == NULL) || inferred_type->is_nullable(); + TraceStrongModeType(this, param->type()); + return CompileType::FromAbstractType(param->type(), is_nullable); + } + // Last resort: use inferred non-nullability. + if (inferred_type != NULL) { + TraceStrongModeType(this, inferred_type); + return *inferred_type; } } @@ -1260,25 +1250,23 @@ CompileType InstanceCallBaseInstr::ComputeType() const { return *inferred_type; } - if (Isolate::Current()->can_use_strong_mode_types()) { - const Function& target = interface_target(); - if (!target.IsNull()) { - const AbstractType& result_type = - AbstractType::ZoneHandle(target.result_type()); - // Currently VM doesn't have enough information to instantiate generic - // result types of interface targets: - // 1. receiver type inferred by the front-end is not passed to VM. - // 2. VM collects type arguments through the chain of superclasses but - // not through implemented interfaces. - // So treat non-instantiated generic types as dynamic to avoid pretending - // the type is known. - // TODO(dartbug.com/30480): instantiate generic result_type - if (result_type.IsInstantiated()) { - TraceStrongModeType(this, result_type); - const bool is_nullable = - (inferred_type == NULL) || inferred_type->is_nullable(); - return CompileType::FromAbstractType(result_type, is_nullable); - } + const Function& target = interface_target(); + if (!target.IsNull()) { + const AbstractType& result_type = + AbstractType::ZoneHandle(target.result_type()); + // Currently VM doesn't have enough information to instantiate generic + // result types of interface targets: + // 1. receiver type inferred by the front-end is not passed to VM. + // 2. VM collects type arguments through the chain of superclasses but + // not through implemented interfaces. + // So treat non-instantiated generic types as dynamic to avoid pretending + // the type is known. + // TODO(dartbug.com/30480): instantiate generic result_type + if (result_type.IsInstantiated()) { + TraceStrongModeType(this, result_type); + const bool is_nullable = + (inferred_type == NULL) || inferred_type->is_nullable(); + return CompileType::FromAbstractType(result_type, is_nullable); } } @@ -1336,30 +1324,25 @@ CompileType StaticCallInstr::ComputeType() const { } } - if (Isolate::Current()->can_use_strong_mode_types()) { - const AbstractType& result_type = - AbstractType::ZoneHandle(function().result_type()); - // TODO(dartbug.com/30480): instantiate generic result_type if possible. - // Also, consider fixing AbstractType::IsSubtypeOf to handle - // non-instantiated types properly. - if (result_type.IsInstantiated()) { - TraceStrongModeType(this, result_type); - is_nullable = is_nullable && - (inferred_type == nullptr || inferred_type->is_nullable()); - return CompileType::FromAbstractType(result_type, is_nullable); - } + const AbstractType& result_type = + AbstractType::ZoneHandle(function().result_type()); + // TODO(dartbug.com/30480): instantiate generic result_type if possible. + // Also, consider fixing AbstractType::IsSubtypeOf to handle + // non-instantiated types properly. + if (result_type.IsInstantiated()) { + TraceStrongModeType(this, result_type); + is_nullable = is_nullable && + (inferred_type == nullptr || inferred_type->is_nullable()); + return CompileType::FromAbstractType(result_type, is_nullable); } return CompileType::Dynamic(); } CompileType LoadLocalInstr::ComputeType() const { - if (Isolate::Current()->can_use_strong_mode_types()) { - const AbstractType& local_type = local().type(); - TraceStrongModeType(this, local_type); - return CompileType::FromAbstractType(local_type); - } - return CompileType::Dynamic(); + const AbstractType& local_type = local().type(); + TraceStrongModeType(this, local_type); + return CompileType::FromAbstractType(local_type); } CompileType DropTempsInstr::ComputeType() const { @@ -1385,15 +1368,11 @@ CompileType StringInterpolateInstr::ComputeType() const { } CompileType LoadStaticFieldInstr::ComputeType() const { - bool is_nullable = CompileType::kNullable; - intptr_t cid = kDynamicCid; - AbstractType* abstract_type = NULL; const Field& field = this->StaticField(); - if (Isolate::Current()->can_use_strong_mode_types()) { - cid = kIllegalCid; // Abstract type is known, calculate cid lazily. - abstract_type = &AbstractType::ZoneHandle(field.type()); - TraceStrongModeType(this, *abstract_type); - } + bool is_nullable = CompileType::kNullable; + intptr_t cid = kIllegalCid; // Abstract type is known, calculate cid lazily. + AbstractType* abstract_type = &AbstractType::ZoneHandle(field.type()); + TraceStrongModeType(this, *abstract_type); ASSERT(field.is_static()); const bool is_initialized = IsFieldInitialized() && !FLAG_fields_may_be_reset; if (field.is_final() && is_initialized) { @@ -1448,13 +1427,8 @@ CompileType LoadFieldInstr::ComputeType() const { return compile_type_cid; } - const Isolate* isolate = Isolate::Current(); - const AbstractType* abstract_type = NULL; - if (isolate->can_use_strong_mode_types() || - (field_type.IsFunctionType() || field_type.HasTypeClass())) { - abstract_type = &field_type; - TraceStrongModeType(this, *abstract_type); - } + const AbstractType* abstract_type = &field_type; + TraceStrongModeType(this, *abstract_type); if (compile_type_cid.ToNullableCid() != kDynamicCid) { abstract_type = nullptr; @@ -1538,20 +1512,17 @@ CompileType UnaryInt64OpInstr::ComputeType() const { } CompileType CheckedSmiOpInstr::ComputeType() const { - if (Isolate::Current()->can_use_strong_mode_types()) { - if (left()->Type()->IsNullableInt() && right()->Type()->IsNullableInt()) { - const AbstractType& abstract_type = - AbstractType::ZoneHandle(Type::IntType()); - TraceStrongModeType(this, abstract_type); - return CompileType::FromAbstractType(abstract_type, - CompileType::kNonNullable); - } else { - CompileType* type = call()->Type(); - TraceStrongModeType(this, type); - return *type; - } + if (left()->Type()->IsNullableInt() && right()->Type()->IsNullableInt()) { + const AbstractType& abstract_type = + AbstractType::ZoneHandle(Type::IntType()); + TraceStrongModeType(this, abstract_type); + return CompileType::FromAbstractType(abstract_type, + CompileType::kNonNullable); + } else { + CompileType* type = call()->Type(); + TraceStrongModeType(this, type); + return *type; } - return CompileType::Dynamic(); } bool CheckedSmiOpInstr::RecomputeType() { @@ -1559,12 +1530,9 @@ bool CheckedSmiOpInstr::RecomputeType() { } CompileType CheckedSmiComparisonInstr::ComputeType() const { - if (Isolate::Current()->can_use_strong_mode_types()) { - CompileType* type = call()->Type(); - TraceStrongModeType(this, type); - return *type; - } - return CompileType::Dynamic(); + CompileType* type = call()->Type(); + TraceStrongModeType(this, type); + return *type; } CompileType BoxIntegerInstr::ComputeType() const { diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc index 750c41da393..4369236eed3 100644 --- a/runtime/vm/compiler/call_specializer.cc +++ b/runtime/vm/compiler/call_specializer.cc @@ -261,7 +261,6 @@ void CallSpecializer::AddCheckNull(Value* to_check, intptr_t deopt_id, Environment* deopt_environment, Instruction* insert_before) { - ASSERT(I->can_use_strong_mode_types()); if (to_check->Type()->is_nullable()) { CheckNullInstr* check_null = new (Z) CheckNullInstr(to_check->CopyWithType(Z), function_name, @@ -867,7 +866,7 @@ bool CallSpecializer::TryInlineInstanceSetter(InstanceCallInstr* instr) { // Build an AssertAssignable if necessary. const AbstractType& dst_type = AbstractType::ZoneHandle(zone(), field.type()); - if (I->argument_type_checks() && !dst_type.IsTopTypeForSubtyping()) { + if (!dst_type.IsTopTypeForSubtyping()) { // Compute if we need to type check the value. Always type check if // at a dynamic invocation. bool needs_check = true; @@ -1204,7 +1203,6 @@ bool CallSpecializer::TryReplaceInstanceOfWithRangeCheck( bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes( InstanceCallInstr* call, const AbstractType& type) { - ASSERT(I->can_use_strong_mode_types()); ASSERT(Token::IsTypeTestOperator(call->token_kind())); if (!type.IsInstantiated()) { return false; @@ -1274,8 +1272,7 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) { type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); } - if (I->can_use_strong_mode_types() && - TryOptimizeInstanceOfUsingStaticTypes(call, type)) { + if (TryOptimizeInstanceOfUsingStaticTypes(call, type)) { return; } @@ -1408,8 +1405,7 @@ void CallSpecializer::VisitStaticCall(StaticCallInstr* call) { } } - if (I->can_use_strong_mode_types() && - TryOptimizeStaticCallUsingStaticTypes(call)) { + if (TryOptimizeStaticCallUsingStaticTypes(call)) { return; } } diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc index 67faab315c0..6ab86e8b4f0 100644 --- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc @@ -830,9 +830,6 @@ JoinEntryInstr* BaseFlowGraphBuilder::BuildThrowNoSuchMethod() { } Fragment BaseFlowGraphBuilder::AssertBool(TokenPosition position) { - if (!I->should_emit_strong_mode_checks()) { - return Fragment(); - } Value* value = Pop(); AssertBooleanInstr* instr = new (Z) AssertBooleanInstr(position, value, GetNextDeoptId()); @@ -1111,10 +1108,6 @@ Fragment BaseFlowGraphBuilder::AssertAssignable( const AbstractType& dst_type, const String& dst_name, AssertAssignableInstr::Kind kind) { - if (!I->should_emit_strong_mode_checks()) { - return Drop() + Drop(); - } - Value* function_type_args = Pop(); Value* instantiator_type_args = Pop(); Value* value = Pop(); diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc index 23dcf66eaee..fa4e6cf9405 100644 --- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc +++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc @@ -2105,7 +2105,7 @@ UncheckedEntryPointStyle BytecodeFlowGraphBuilder::ChooseEntryPointStyle( const KBCInstr* jump_if_unchecked) { ASSERT(KernelBytecode::IsJumpIfUncheckedOpcode(jump_if_unchecked)); - if (!function().MayHaveUncheckedEntryPoint(isolate())) { + if (!function().MayHaveUncheckedEntryPoint()) { return UncheckedEntryPointStyle::kNone; } diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc index 9295cb64771..99cad2f14ff 100644 --- a/runtime/vm/compiler/frontend/bytecode_reader.cc +++ b/runtime/vm/compiler/frontend/bytecode_reader.cc @@ -912,7 +912,7 @@ intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function, // checked at the entry because the parameter is marked covariant, // neither of those cases require a dynamic invocation forwarder; // * we assume that all closures are entered in a checked way. - if (!Field::IsGetterName(name) && I->should_emit_strong_mode_checks() && + if (!Field::IsGetterName(name) && (name.raw() != Symbols::EqualOperator().raw()) && (name.raw() != Symbols::Call().raw())) { name = Function::CreateDynamicInvocationForwarderName(name); diff --git a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc index bc1a30b8427..2a5e79f0bb0 100644 --- a/runtime/vm/compiler/frontend/bytecode_scope_builder.cc +++ b/runtime/vm/compiler/frontend/bytecode_scope_builder.cc @@ -137,8 +137,7 @@ void BytecodeScopeBuilder::BuildScopes() { if (needs_expr_temp) { scope_->AddVariable(parsed_function_->EnsureExpressionTemp()); } - if (parsed_function_->function().MayHaveUncheckedEntryPoint( - parsed_function_->isolate())) { + if (parsed_function_->function().MayHaveUncheckedEntryPoint()) { scope_->AddVariable(parsed_function_->EnsureEntryPointsTemp()); } parsed_function_->AllocateVariables(); diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index 3079ccf712c..0ea4e895c80 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -763,7 +763,7 @@ void StreamingFlowGraphBuilder::CheckArgumentTypesAsNecessary( Fragment* explicit_checks, Fragment* implicit_checks, Fragment* implicit_redefinitions) { - if (!dart_function.NeedsArgumentTypeChecks(I)) return; + if (!dart_function.NeedsArgumentTypeChecks()) return; // Check if parent function was annotated with no-dynamic-invocations. const ProcedureAttributesMetadata attrs = @@ -903,7 +903,7 @@ UncheckedEntryPointStyle StreamingFlowGraphBuilder::ChooseEntryPointStyle( const Fragment& every_time_prologue, const Fragment& type_args_handling) { ASSERT(!dart_function.IsImplicitClosureFunction()); - if (!dart_function.MayHaveUncheckedEntryPoint(I) || + if (!dart_function.MayHaveUncheckedEntryPoint() || implicit_type_checks.is_empty()) { return UncheckedEntryPointStyle::kNone; } @@ -2437,7 +2437,7 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) { const String* mangled_name = &setter_name; const Function* direct_call_target = &direct_call.target_; - if (I->should_emit_strong_mode_checks() && H.IsRoot(itarget_name)) { + if (H.IsRoot(itarget_name)) { mangled_name = &String::ZoneHandle( Z, Function::CreateDynamicInvocationForwarderName(setter_name)); if (!direct_call_target->IsNull()) { @@ -3014,8 +3014,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) { // those cases require a dynamic invocation forwarder; // * we assume that all closures are entered in a checked way. const Function* direct_call_target = &direct_call.target_; - if (I->should_emit_strong_mode_checks() && - (name.raw() != Symbols::EqualOperator().raw()) && + if ((name.raw() != Symbols::EqualOperator().raw()) && (name.raw() != Symbols::Call().raw()) && H.IsRoot(itarget_name)) { mangled_name = &String::ZoneHandle( Z, Function::CreateDynamicInvocationForwarderName(name)); diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index de871759480..62ce5a75552 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -1534,9 +1534,6 @@ Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type, const String& dst_name, AssertAssignableInstr::Kind kind) { Fragment instructions; - if (!I->should_emit_strong_mode_checks()) { - return Fragment(); - } if (!dst_type.IsTopTypeForSubtyping()) { LocalVariable* top_of_stack = MakeTemporary(); instructions += LoadLocal(top_of_stack); @@ -1552,10 +1549,6 @@ Fragment FlowGraphBuilder::AssertAssignableLoadTypeArguments( const AbstractType& dst_type, const String& dst_name, AssertAssignableInstr::Kind kind) { - if (!I->should_emit_strong_mode_checks()) { - return Fragment(); - } - Fragment instructions; if (!dst_type.IsInstantiated(kCurrentClass)) { @@ -1599,7 +1592,6 @@ void FlowGraphBuilder::BuildArgumentTypeChecks( Fragment* explicit_checks, Fragment* implicit_checks, Fragment* implicit_redefinitions) { - if (!I->should_emit_strong_mode_checks()) return; const Function& dart_function = parsed_function_->function(); const Function* forwarding_target = nullptr; @@ -2033,7 +2025,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder( } } - if (function.NeedsArgumentTypeChecks(I)) { + if (function.NeedsArgumentTypeChecks()) { BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds, &body, &body, nullptr); } @@ -2402,7 +2394,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( // We're going to throw away the explicit checks because the target will // always check them. Fragment implicit_checks; - if (function.NeedsArgumentTypeChecks(I)) { + if (function.NeedsArgumentTypeChecks()) { Fragment explicit_checks_unused; if (target.is_static()) { // Tearoffs of static methods needs to perform arguments checks since @@ -2460,7 +2452,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction( // Setup multiple entrypoints if useful. FunctionEntryInstr* extra_entry = nullptr; - if (function.MayHaveUncheckedEntryPoint(I)) { + if (function.MayHaveUncheckedEntryPoint()) { // The prologue for a closure will always have context handling (e.g. // setting up the receiver variable), but we don't need it on the unchecked // entry because the only time we reference this is for loading the @@ -2538,7 +2530,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor( body += LoadLocal(parsed_function_->ParameterVariable(0)); } body += LoadLocal(setter_value); - if (I->argument_type_checks() && setter_value->needs_type_check()) { + if (setter_value->needs_type_check()) { body += CheckAssignable(setter_value->type(), setter_value->name(), AssertAssignableInstr::kParameterCheck); } diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc index 78903eff080..a1582ac6a49 100644 --- a/runtime/vm/compiler/frontend/scope_builder.cc +++ b/runtime/vm/compiler/frontend/scope_builder.cc @@ -430,7 +430,7 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() { if (needs_expr_temp_) { scope_->AddVariable(parsed_function_->EnsureExpressionTemp()); } - if (parsed_function_->function().MayHaveUncheckedEntryPoint(I)) { + if (parsed_function_->function().MayHaveUncheckedEntryPoint()) { scope_->AddVariable(parsed_function_->EnsureEntryPointsTemp()); } parsed_function_->AllocateVariables(); diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc index 3a42c2dcdb5..fc8fa3da05c 100644 --- a/runtime/vm/compiler/graph_intrinsifier.cc +++ b/runtime/vm/compiler/graph_intrinsifier.cc @@ -748,14 +748,6 @@ bool GraphIntrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { return true; } -bool GraphIntrinsifier::Build_ObjectArraySetIndexed(FlowGraph* flow_graph) { - if (Isolate::Current()->argument_type_checks()) { - return false; - } - - return Build_ObjectArraySetIndexedUnchecked(flow_graph); -} - bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked( FlowGraph* flow_graph) { GraphEntryInstr* graph_entry = flow_graph->graph_entry(); @@ -780,14 +772,6 @@ bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked( return true; } -bool GraphIntrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { - if (Isolate::Current()->argument_type_checks()) { - return false; - } - - return Build_GrowableArraySetIndexedUnchecked(flow_graph); -} - bool GraphIntrinsifier::Build_GrowableArraySetIndexedUnchecked( FlowGraph* flow_graph) { GraphEntryInstr* graph_entry = flow_graph->graph_entry(); diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h index 2fd4cd7e227..c26d1f8dfe2 100644 --- a/runtime/vm/compiler/recognized_methods_list.h +++ b/runtime/vm/compiler/recognized_methods_list.h @@ -17,6 +17,8 @@ namespace dart { V(Object, Object., ObjectConstructor, 0x8f3ae7ea) \ V(List, ., ListFactory, 0xdf9970a9) \ V(_List, ., ObjectArrayAllocate, 0x03ddbd3a) \ + V(_List, []=, ObjectArraySetIndexed, 0x4d5e74cf) \ + V(_GrowableList, []=, GrowableArraySetIndexed, 0x4d5e74cf) \ V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0xa24c2704) \ V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0xa491df3e) \ V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0xb65ae1fc) \ @@ -347,7 +349,6 @@ namespace dart { #define GRAPH_CORE_INTRINSICS_LIST(V) \ V(_List, get:length, ObjectArrayLength, 0x05176aac) \ V(_List, [], ObjectArrayGetIndexed, 0x7e13418e) \ - V(_List, []=, ObjectArraySetIndexed, 0x4d5e74cf) \ V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, 0x91b2c203) \ V(_ImmutableList, get:length, ImmutableArrayLength, 0x05176aac) \ V(_ImmutableList, [], ImmutableArrayGetIndexed, 0x7e13418e) \ @@ -356,7 +357,6 @@ namespace dart { V(_GrowableList, _setData, GrowableArraySetData, 0x9e2350fe) \ V(_GrowableList, _setLength, GrowableArraySetLength, 0x8d94d91d) \ V(_GrowableList, [], GrowableArrayGetIndexed, 0x7e13418e) \ - V(_GrowableList, []=, GrowableArraySetIndexed, 0x4d5e74cf) \ V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, 0x91b2c203) \ V(_StringBase, get:length, StringBaseLength, 0x05176aac) \ V(_OneByteString, codeUnitAt, OneByteStringCodeUnitAt, 0xb0959953) \ diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h index 8fdc0ded63a..605385f8a38 100644 --- a/runtime/vm/flag_list.h +++ b/runtime/vm/flag_list.h @@ -85,9 +85,6 @@ constexpr bool kDartUseBackgroundCompilation = true; #define FLAG_LIST(P, R, C, D) \ VM_GLOBAL_FLAG_LIST(P, R, C, D) \ DISASSEMBLE_FLAGS(P, R, C, D) \ - P(experimental_unsafe_mode_use_at_your_own_risk, bool, false, \ - "Omit runtime strong mode type checks and disable optimizations based on " \ - "types.") \ P(abort_on_oom, bool, false, \ "Abort if memory allocation fails - use only with --old-gen-heap-size") \ C(async_debugger, false, false, bool, true, \ @@ -233,7 +230,6 @@ constexpr bool kDartUseBackgroundCompilation = true; "Use class hierarchy analysis even if it can cause deoptimization.") \ P(use_field_guards, bool, true, "Use field guards and track field types") \ C(use_osr, false, true, bool, true, "Use OSR") \ - P(use_strong_mode_types, bool, true, "Optimize based on strong mode types.") \ R(verbose_gc, false, bool, false, "Enables verbose GC.") \ R(verbose_gc_hdr, 40, int, 40, "Print verbose GC header interval.") \ R(verify_after_gc, false, bool, false, \ diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index d1790b1b2b3..b8c12f0799e 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -164,10 +164,7 @@ typedef FixedCache CatchEntryMovesCache; V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \ FLAG_use_field_guards) \ V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \ - V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false_by_default) \ - V(PRODUCT, unsafe_trust_strong_mode_types, UnsafeTrustStrongModeTypes, \ - unsafe_trust_strong_mode_types, \ - FLAG_experimental_unsafe_mode_use_at_your_own_risk) + V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false_by_default) // Represents the information used for spawning the first isolate within an // isolate group. @@ -1144,10 +1141,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { isolate_flags_ = IsKernelIsolateBit::update(value, isolate_flags_); } - bool can_use_strong_mode_types() const { - return FLAG_use_strong_mode_types && !unsafe_trust_strong_mode_types(); - } - // Whether it's possible for unoptimized code to optimize immediately on entry // (can happen with random or very low optimization counter thresholds) bool CanOptimizeImmediately() const { @@ -1230,14 +1223,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { isolate_flags_ = NullSafetyBit::update(null_safety, isolate_flags_); } - // Convenience flag tester indicating whether incoming function arguments - // should be type checked. - bool argument_type_checks() const { return should_emit_strong_mode_checks(); } - - bool should_emit_strong_mode_checks() const { - return !unsafe_trust_strong_mode_types(); - } - bool has_attempted_stepping() const { return HasAttemptedSteppingBit::decode(isolate_flags_); } @@ -1400,8 +1385,7 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { V(Obfuscate) \ V(ShouldLoadVmService) \ V(NullSafety) \ - V(NullSafetySet) \ - V(UnsafeTrustStrongModeTypes) + V(NullSafetySet) // Isolate specific flags. enum FlagBits { diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc index a67d70a12da..9fe4c5f20e0 100644 --- a/runtime/vm/kernel_isolate.cc +++ b/runtime/vm/kernel_isolate.cc @@ -86,7 +86,6 @@ class RunKernelTask : public ThreadPool::Task { Dart_IsolateFlags api_flags; Isolate::FlagsInitialize(&api_flags); api_flags.enable_asserts = false; - api_flags.unsafe_trust_strong_mode_types = false; #if !defined(DART_PRECOMPILER) api_flags.use_field_guards = true; #endif diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 0cc1cfa948a..84112b10f39 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -9180,9 +9180,9 @@ bool Function::NeedsMonomorphicCheckedEntry(Zone* zone) const { #endif } -bool Function::MayHaveUncheckedEntryPoint(Isolate* I) const { +bool Function::MayHaveUncheckedEntryPoint() const { return FLAG_enable_multiple_entrypoints && - (NeedsArgumentTypeChecks(I) || IsImplicitClosureFunction()); + (NeedsArgumentTypeChecks() || IsImplicitClosureFunction()); } const char* Function::ToCString() const { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 469f0279bdf..a42898b5b89 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -2854,17 +2854,14 @@ class Function : public Object { } bool IsInFactoryScope() const; - bool NeedsArgumentTypeChecks(Isolate* I) const { - if (!I->should_emit_strong_mode_checks()) { - return false; - } + bool NeedsArgumentTypeChecks() const { return IsClosureFunction() || !(is_static() || (kind() == FunctionLayout::kConstructor)); } bool NeedsMonomorphicCheckedEntry(Zone* zone) const; - bool MayHaveUncheckedEntryPoint(Isolate* I) const; + bool MayHaveUncheckedEntryPoint() const; TokenPosition token_pos() const { #if defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h index 6d6166f2969..8cf342c9176 100644 --- a/runtime/vm/scopes.h +++ b/runtime/vm/scopes.h @@ -151,10 +151,7 @@ class LocalVariable : public ZoneAllocated { // Returns true if this local variable represents a parameter that needs type // check when we enter the function. - bool needs_type_check() const { - return (type_check_mode_ == kDoTypeCheck) && - Isolate::Current()->should_emit_strong_mode_checks(); - } + bool needs_type_check() const { return (type_check_mode_ == kDoTypeCheck); } // Returns true if this local variable represents a parameter which type is // guaranteed by the caller.