Skip to content

Commit 6bc1cdb

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm] Add unsafe mode to VM
This CL adds experimental --experimental-unsafe-mode-use-at-your-own-risk VM option which does the following: * Dart 2 strong mode type and bool checks are omitted. * VM compiler optimizations which rely on strong mode types are disabled. Applications which do not fail any strong mode checks at run time should behave exactly the same in strong and weak modes. Applications with failing strong mode checks will not see corresponding errors but VM should not crash. This option can be used for experiments, or as a temporary remedy for regressions caused by expensive strong mode type checks. Change-Id: I042cbccba83c105b61b3e11c659a35c20e0329cd Reviewed-on: https://dart-review.googlesource.com/65484 Reviewed-by: Siva Annamalai <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent cadc4c3 commit 6bc1cdb

File tree

8 files changed

+40
-4
lines changed

8 files changed

+40
-4
lines changed

runtime/vm/compiler/backend/type_propagator.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void FlowGraphTypePropagator::PropagateRecursive(BlockEntryInstr* block) {
130130
// can contain [AssertAssignableInstr]s and we therefore enable this
131131
// optimization.
132132
Isolate* isolate = Isolate::Current();
133-
if (isolate->type_checks() || isolate->strong()) {
133+
if (isolate->argument_type_checks()) {
134134
StrengthenAsserts(block);
135135
}
136136

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,10 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
880880

881881
Fragment StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
882882
TypeChecksToBuild mode) {
883+
if (FLAG_omit_strong_type_checks) {
884+
return Fragment();
885+
}
886+
883887
FunctionNodeHelper function_node_helper(this);
884888
function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
885889
const Function& dart_function = parsed_function()->function();
@@ -2627,7 +2631,8 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) {
26272631
const intptr_t kNumArgsChecked = 1;
26282632

26292633
const String* mangled_name = &setter_name;
2630-
if (!FLAG_precompiled_mode && I->strong() && H.IsRoot(itarget_name)) {
2634+
if (!FLAG_precompiled_mode && I->strong() &&
2635+
!FLAG_omit_strong_type_checks && H.IsRoot(itarget_name)) {
26312636
mangled_name = &String::ZoneHandle(
26322637
Z, Function::CreateDynamicInvocationForwarderName(setter_name));
26332638
}
@@ -3201,6 +3206,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
32013206
// those cases require a dynamic invocation forwarder;
32023207
// * we assume that all closures are entered in a checked way.
32033208
if (!FLAG_precompiled_mode && I->strong() &&
3209+
!FLAG_omit_strong_type_checks &&
32043210
(name.raw() != Symbols::EqualOperator().raw()) &&
32053211
(name.raw() != Symbols::Call().raw()) && H.IsRoot(itarget_name)) {
32063212
mangled_name = &String::ZoneHandle(

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,9 @@ Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type,
15711571
if (dst_type.IsMalformed()) {
15721572
return ThrowTypeError();
15731573
}
1574+
if (FLAG_omit_strong_type_checks) {
1575+
return Fragment();
1576+
}
15741577
if (!dst_type.IsDynamicType() && !dst_type.IsObjectType() &&
15751578
!dst_type.IsVoidType()) {
15761579
LocalVariable* top_of_stack = MakeTemporary();
@@ -1583,6 +1586,9 @@ Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type,
15831586
}
15841587

15851588
Fragment FlowGraphBuilder::AssertBool(TokenPosition position) {
1589+
if (FLAG_omit_strong_type_checks) {
1590+
return Fragment();
1591+
}
15861592
Value* value = Pop();
15871593
AssertBooleanInstr* instr =
15881594
new (Z) AssertBooleanInstr(position, value, GetNextDeoptId());
@@ -1594,6 +1600,10 @@ Fragment FlowGraphBuilder::AssertAssignable(TokenPosition position,
15941600
const AbstractType& dst_type,
15951601
const String& dst_name,
15961602
AssertAssignableInstr::Kind kind) {
1603+
if (FLAG_omit_strong_type_checks) {
1604+
return Fragment();
1605+
}
1606+
15971607
Fragment instructions;
15981608
Value* value = Pop();
15991609

runtime/vm/compiler/jit/compiler.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ DEFINE_FLAG_HANDLER(PrecompilationModeHandler,
133133
precompilation,
134134
"Precompilation mode");
135135

136+
static void UnsafeModeHandler(bool value) {
137+
if (value) {
138+
FLAG_omit_strong_type_checks = true;
139+
FLAG_use_strong_mode_types = false;
140+
}
141+
}
142+
143+
DEFINE_FLAG_HANDLER(UnsafeModeHandler,
144+
experimental_unsafe_mode_use_at_your_own_risk,
145+
"Omit runtime strong mode type checks and disable "
146+
"optimizations based on types.");
147+
136148
#ifndef DART_PRECOMPILED_RUNTIME
137149

138150
bool UseKernelFrontEndFor(ParsedFunction* parsed_function) {

runtime/vm/flag_list.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ constexpr bool kDartPrecompiledRuntime = false;
122122
"Max size of new gen semi space in MB") \
123123
P(new_gen_semi_initial_size, int, (kWordSize <= 4) ? 1 : 2, \
124124
"Initial size of new gen semi space in MB") \
125+
P(omit_strong_type_checks, bool, false, "Omit strong mode type checks.") \
125126
P(optimization_counter_threshold, int, 30000, \
126127
"Function's usage-counter value before it is optimized, -1 means never") \
127128
P(old_gen_heap_size, int, kDefaultMaxOldGenHeapSize, \

runtime/vm/isolate.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,9 @@ class Isolate : public BaseIsolate {
749749

750750
// Convenience flag tester indicating whether incoming function arguments
751751
// should be type checked.
752-
bool argument_type_checks() { return strong() || type_checks(); }
752+
bool argument_type_checks() {
753+
return (strong() && !FLAG_omit_strong_type_checks) || type_checks();
754+
}
753755

754756
static void KillAllIsolates(LibMsgId msg_id);
755757
static void KillIfExists(Isolate* isolate, LibMsgId msg_id);

runtime/vm/object.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2428,6 +2428,9 @@ class Function : public Object {
24282428

24292429
bool NeedsArgumentTypeChecks(Isolate* I) const {
24302430
if (I->strong()) {
2431+
if (FLAG_omit_strong_type_checks) {
2432+
return false;
2433+
}
24312434
return IsNonImplicitClosureFunction() ||
24322435
!(is_static() || (kind() == RawFunction::kConstructor));
24332436
}

runtime/vm/scopes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ class LocalVariable : public ZoneAllocated {
129129

130130
// Returns true if this local variable represents a parameter that needs type
131131
// check when we enter the function.
132-
bool needs_type_check() const { return type_check_mode_ == kDoTypeCheck; }
132+
bool needs_type_check() const {
133+
return (type_check_mode_ == kDoTypeCheck) && !FLAG_omit_strong_type_checks;
134+
}
133135

134136
// Returns true if this local variable represents a parameter which type is
135137
// guaranteed by the caller.

0 commit comments

Comments
 (0)