Skip to content

Commit

Permalink
[VM] Introduce function and osr entrypoints to the VM's IR
Browse files Browse the repository at this point in the history
Similar to how we treat catch entry instructions, this cl adds new
function and osr entry instructions. The [FunctionEntry] and
[OsrEntry] - just like [CatchBlockEntry] - have now their own initial
definitions. The [GraphEntry] has only initial definitions for
constants.

Explicit phis are inserted for all parameter / special parameter
instructions if necessary.

Future work is:

  a) Minimize parallel moves due to the phis on parameters
  b) Cleanup frame setup: Move it entirely into FunctionEntry/CatchEntry
    (instead of the split version we have now)

Fixes #34435
Fixes #34287

Change-Id: Iefa0280a709716f748d6fb0523b8d0f4d8de1fec
Reviewed-on: https://dart-review.googlesource.com/c/74782
Commit-Queue: Martin Kustermann <[email protected]>
Reviewed-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
mkustermann authored and [email protected] committed Oct 15, 2018
1 parent 22b1171 commit 06f9a9e
Show file tree
Hide file tree
Showing 38 changed files with 1,061 additions and 539 deletions.
17 changes: 8 additions & 9 deletions runtime/observatory/tests/service/rewind_test.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) 2016, 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.
// VMOptions=--no-sync-async

import 'dart:developer';
import 'package:observatory/service_io.dart';
Expand All @@ -12,10 +11,10 @@ import 'test_helper.dart';
const alwaysInline = "AlwaysInline";
const noInline = "NeverInline";

int LINE_A = 35;
int LINE_B = 40;
int LINE_C = 43;
int LINE_D = 47;
int LINE_A = 34;
int LINE_B = 39;
int LINE_C = 42;
int LINE_D = 46;

int global = 0;

Expand Down Expand Up @@ -60,20 +59,20 @@ var tests = <IsolateTest>[
} on ServerRpcException catch (e) {
caughtException = true;
expect(e.code, equals(ServerRpcException.kCannotResume));
expect(e.message, 'Frame must be in bounds [1..9]: saw 0');
expect(e.message, 'Frame must be in bounds [1..12]: saw 0');
}
expect(caughtException, isTrue);
},
(Isolate isolate) async {
// We are not able to rewind frame 10.
// We are not able to rewind frame 13.
bool caughtException;
try {
await isolate.rewind(10);
await isolate.rewind(13);
expect(false, isTrue, reason: 'Unreachable');
} on ServerRpcException catch (e) {
caughtException = true;
expect(e.code, equals(ServerRpcException.kCannotResume));
expect(e.message, 'Frame must be in bounds [1..9]: saw 10');
expect(e.message, 'Frame must be in bounds [1..12]: saw 13');
}
expect(caughtException, isTrue);
},
Expand Down
2 changes: 1 addition & 1 deletion runtime/observatory/tests/service/service.status
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ step_through_getter_test: RuntimeError # Debugging StringConcatenation doesn't w
*: SkipByDesign

[ $compiler == dartk || $compiler == dartkp ]
rewind_test: Pass, RuntimeError, Slow # Issue 34287
rewind_test: Pass, Slow

# Skip all service tests because random reloads interfere.
[ $hot_reload || $hot_reload_rollback ]
Expand Down
3 changes: 3 additions & 0 deletions runtime/tests/vm/vm.status
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ dart/simd128float32_test: Skip # compilers not aware of Simd128
dart/truncating_ints_test: SkipByDesign # The test requires int64.
dart/wrap_around_in_range_analysis_test: SkipByDesign # The test requires int64.

[ $compiler != dartk || ($arch != x64 && $arch != simarm && $arch != arm) || $hot_reload || $hot_reload_rollback ]
dart/entrypoints/*: Skip # Only supported in Dart 2 JIT (hot-reload -> issue 34199).

[ ($compiler == dartk || $compiler == dartkb) ]
cc/DartAPI_New: Fail # Issue #33041
dart/redirection_type_shuffling_test/00: RuntimeError, Pass
Expand Down
13 changes: 9 additions & 4 deletions runtime/vm/compiler/backend/block_scheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,15 @@ void BlockScheduler::AssignEdgeWeights() const {
Array& edge_counters = Array::Handle();
edge_counters ^= ic_data_array.At(0);

intptr_t entry_count = GetEdgeCount(
edge_counters,
flow_graph()->graph_entry()->normal_entry()->preorder_number());
flow_graph()->graph_entry()->set_entry_count(entry_count);
auto graph_entry = flow_graph()->graph_entry();
BlockEntryInstr* entry = graph_entry->normal_entry();
if (entry == nullptr) {
entry = graph_entry->osr_entry();
ASSERT(entry != nullptr);
}
const intptr_t entry_count =
GetEdgeCount(edge_counters, entry->preorder_number());
graph_entry->set_entry_count(entry_count);

for (BlockIterator it = flow_graph()->reverse_postorder_iterator();
!it.Done(); it.Advance()) {
Expand Down
13 changes: 12 additions & 1 deletion runtime/vm/compiler/backend/branch_optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ bool BranchSimplifier::Match(JoinEntryInstr* block) {
}

JoinEntryInstr* BranchSimplifier::ToJoinEntry(Zone* zone,
TargetEntryInstr* target) {
BlockEntryInstr* target) {
// Convert a target block into a join block. Branches will be duplicated
// so the former true and false targets become joins of the control flows
// from all the duplicated branches.
Expand All @@ -74,6 +74,17 @@ JoinEntryInstr* BranchSimplifier::ToJoinEntry(Zone* zone,
return join;
}

TargetEntryInstr* BranchSimplifier::ToTargetEntry(Zone* zone,
BlockEntryInstr* target) {
auto replacement = new (zone)
TargetEntryInstr(target->block_id(), target->try_index(), DeoptId::kNone);
replacement->InheritDeoptTarget(zone, target);
replacement->LinkTo(target->next());
replacement->set_last_instruction(target->last_instruction());
target->UnuseAllInputs();
return replacement;
}

BranchInstr* BranchSimplifier::CloneBranch(Zone* zone,
BranchInstr* branch,
Value* new_left,
Expand Down
11 changes: 9 additions & 2 deletions runtime/vm/compiler/backend/branch_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

namespace dart {

class BlockEntryInstr;
class FlowGraph;
class FunctionEntryInstr;
class JoinEntryInstr;
class Zone;
class TargetEntryInstr;
Expand All @@ -23,10 +25,15 @@ class BranchSimplifier : public AllStatic {
public:
static void Simplify(FlowGraph* flow_graph);

// Replace a target entry instruction with a join entry instruction. Does
// Replace a block entry instruction with a join entry instruction. Does
// not update the original target's predecessors to point to the new block
// and does not replace the target in already computed block order lists.
static JoinEntryInstr* ToJoinEntry(Zone* zone, TargetEntryInstr* target);
static JoinEntryInstr* ToJoinEntry(Zone* zone, BlockEntryInstr* target);

// Replace a block entry instruction with a target entry instruction. Does
// not update the original target's predecessors to point to the new block and
// does not replace the target in already computed block order lists.
static TargetEntryInstr* ToTargetEntry(Zone* zone, BlockEntryInstr* target);

private:
// Match an instance of the pattern to rewrite. See the implementation
Expand Down
38 changes: 27 additions & 11 deletions runtime/vm/compiler/backend/constant_propagator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,8 @@ void ConstantPropagator::Join(Object* left, const Object& right) {
// Analysis of blocks. Called at most once per block. The block is already
// marked as reachable. All instructions in the block are analyzed.
void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
const GrowableArray<Definition*>& defs = *block->initial_definitions();
for (intptr_t i = 0; i < defs.length(); ++i) {
defs[i]->Accept(this);
for (auto def : *block->initial_definitions()) {
def->Accept(this);
}
ASSERT(ForwardInstructionIterator(block).Done());

Expand All @@ -134,30 +133,47 @@ void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
}
}

void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
// Phis are visited when visiting Goto at a predecessor. See VisitGoto.
void ConstantPropagator::VisitFunctionEntry(FunctionEntryInstr* block) {
for (auto def : *block->initial_definitions()) {
def->Accept(this);
}
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}

void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
void ConstantPropagator::VisitOsrEntry(OsrEntryInstr* block) {
for (auto def : *block->initial_definitions()) {
def->Accept(this);
}
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}

void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) {
void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
for (auto def : *block->initial_definitions()) {
def->Accept(this);
}
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}

void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
const GrowableArray<Definition*>& defs = *block->initial_definitions();
for (intptr_t i = 0; i < defs.length(); ++i) {
defs[i]->Accept(this);
void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
// Phis are visited when visiting Goto at a predecessor. See VisitGoto.
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}

void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
}

void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) {
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
it.Current()->Accept(this);
}
Expand Down
Loading

0 comments on commit 06f9a9e

Please sign in to comment.