Skip to content

Commit

Permalink
[vm/bytecode] Use local variable information when compiling from byte…
Browse files Browse the repository at this point in the history
…code

This includes types and names of local variables.
Fixes vm/cc/IRTest_TypedDataAOT_FunctionalGetSet with bytecode.

Change-Id: I6130f19b4028f4930dbfcb282b90dd2ec4f963e1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/116082
Reviewed-by: Régis Crelier <regis@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
  • Loading branch information
alexmarkov authored and commit-bot@chromium.org committed Sep 9, 2019
1 parent 27f803d commit ef2a21f
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 49 deletions.
6 changes: 2 additions & 4 deletions runtime/vm/clustered_snapshot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1627,8 +1627,7 @@ class BytecodeSerializationCluster : public SerializationCluster {
WriteFromTo(bytecode);
s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
NOT_IN_PRODUCT(
s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_));
s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_);
}
}

Expand Down Expand Up @@ -1663,8 +1662,7 @@ class BytecodeDeserializationCluster : public DeserializationCluster {
ReadFromTo(bytecode);
bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
NOT_IN_PRODUCT(bytecode->ptr()->local_variables_binary_offset_ =
d->Read<int32_t>());
bytecode->ptr()->local_variables_binary_offset_ = d->Read<int32_t>();
}
}

Expand Down
81 changes: 53 additions & 28 deletions runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2076,34 +2076,62 @@ void BytecodeFlowGraphBuilder::CreateParameterVariables() {
}
}

#if !defined(PRODUCT)
intptr_t BytecodeFlowGraphBuilder::UpdateContextLevel(const Bytecode& bytecode,
intptr_t pc) {
ASSERT(B->is_recording_context_levels());
intptr_t BytecodeFlowGraphBuilder::UpdateScope(
BytecodeLocalVariablesIterator* iter,
intptr_t pc) {
// Leave scopes that have ended.
while ((current_scope_ != nullptr) && (current_scope_->end_pc_ <= pc)) {
for (LocalVariable* local : current_scope_->hidden_vars_) {
local_vars_[-local->index().value()] = local;
}
current_scope_ = current_scope_->parent_;
}

kernel::BytecodeLocalVariablesIterator iter(Z, bytecode);
intptr_t context_level = 0;
// Enter scopes that have started.
intptr_t next_pc = bytecode_length_;
while (iter.MoveNext()) {
if (iter.IsScope()) {
if (iter.StartPC() <= pc) {
if (pc < iter.EndPC()) {
// Found enclosing scope. Keep looking as we might find more
// scopes (the last one is the most specific).
context_level = iter.ContextLevel();
next_pc = iter.EndPC();
}
} else {
next_pc = Utils::Minimum(next_pc, iter.StartPC());
while (!iter->IsDone()) {
if (iter->IsScope()) {
if (iter->StartPC() > pc) {
next_pc = iter->StartPC();
break;
}
if (iter->EndPC() > pc) {
// Push new scope and declare its variables.
current_scope_ = new (Z) BytecodeScope(
Z, iter->EndPC(), iter->ContextLevel(), current_scope_);
if (!seen_parameters_scope_) {
// Skip variables from the first scope as it may contain variables
// which were used in prologue (parameters, function type arguments).
// The already used variables should not be replaced with new ones.
seen_parameters_scope_ = true;
iter->MoveNext();
continue;
}
while (iter->MoveNext() && iter->IsVariableDeclaration()) {
const intptr_t index = iter->Index();
if (!iter->IsCaptured() && (index >= 0)) {
LocalVariable* local = new (Z) LocalVariable(
TokenPosition::kNoSource, TokenPosition::kNoSource,
String::ZoneHandle(Z, iter->Name()),
AbstractType::ZoneHandle(Z, iter->Type()));
local->set_index(VariableIndex(-index));
ASSERT(local_vars_[index]->index().value() == -index);
current_scope_->hidden_vars_.Add(local_vars_[index]);
local_vars_[index] = local;
}
}
continue;
}
}
iter->MoveNext();
}

B->set_context_depth(context_level);
if (current_scope_ != nullptr && next_pc > current_scope_->end_pc_) {
next_pc = current_scope_->end_pc_;
}
B->set_context_depth(
current_scope_ != nullptr ? current_scope_->context_level_ : 0);
return next_pc;
}
#endif // !defined(PRODUCT)

FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
const Bytecode& bytecode = Bytecode::Handle(Z, function().bytecode());
Expand All @@ -2127,10 +2155,9 @@ FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
kernel::BytecodeSourcePositionsIterator source_pos_iter(Z, bytecode);
bool update_position = source_pos_iter.MoveNext();

#if !defined(PRODUCT)
intptr_t next_pc_to_update_context_level =
B->is_recording_context_levels() ? 0 : bytecode_length_;
#endif
kernel::BytecodeLocalVariablesIterator local_vars_iter(Z, bytecode);
intptr_t next_pc_to_update_scope =
local_vars_iter.MoveNext() ? 0 : bytecode_length_;

code_ = Fragment(normal_entry);

Expand Down Expand Up @@ -2164,11 +2191,9 @@ FlowGraph* BytecodeFlowGraphBuilder::BuildGraph() {
update_position = source_pos_iter.MoveNext();
}

#if !defined(PRODUCT)
if (pc_ >= next_pc_to_update_context_level) {
next_pc_to_update_context_level = UpdateContextLevel(bytecode, pc_);
if (pc_ >= next_pc_to_update_scope) {
next_pc_to_update_scope = UpdateScope(&local_vars_iter, pc_);
}
#endif

BuildInstruction(KernelBytecode::DecodeOpcode(bytecode_instr_));

Expand Down
30 changes: 25 additions & 5 deletions runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace dart {
namespace kernel {

class BytecodeLocalVariablesIterator;

// This class builds flow graph from bytecode. It is used either to compile
// from bytecode, or generate bytecode interpreter (the latter is not
// fully implemented yet).
Expand Down Expand Up @@ -107,6 +109,24 @@ class BytecodeFlowGraphBuilder {
const Object& value_;
};

// Scope declared in bytecode local variables information.
class BytecodeScope : public ZoneAllocated {
public:
BytecodeScope(Zone* zone,
intptr_t end_pc,
intptr_t context_level,
BytecodeScope* parent)
: end_pc_(end_pc),
context_level_(context_level),
parent_(parent),
hidden_vars_(zone, 4) {}

const intptr_t end_pc_;
const intptr_t context_level_;
BytecodeScope* const parent_;
ZoneGrowableArray<LocalVariable*> hidden_vars_;
};

Operand DecodeOperandA();
Operand DecodeOperandB();
Operand DecodeOperandC();
Expand Down Expand Up @@ -168,11 +188,9 @@ class BytecodeFlowGraphBuilder {
const ExceptionHandlers& handlers,
GraphEntryInstr* graph_entry);

#if !defined(PRODUCT)
// Update context level for the given bytecode PC. returns
// next PC where context level might need an update.
intptr_t UpdateContextLevel(const Bytecode& bytecode, intptr_t pc);
#endif
// Update current scope, context level and local variables for the given PC.
// Returns next PC where scope might need an update.
intptr_t UpdateScope(BytecodeLocalVariablesIterator* iter, intptr_t pc);

// Figure out entry points style.
UncheckedEntryPointStyle ChooseEntryPointStyle(
Expand Down Expand Up @@ -215,6 +233,8 @@ class BytecodeFlowGraphBuilder {
GraphEntryInstr* graph_entry_ = nullptr;
UncheckedEntryPointStyle entry_point_style_ = UncheckedEntryPointStyle::kNone;
bool build_debug_step_checks_ = false;
bool seen_parameters_scope_ = false;
BytecodeScope* current_scope_ = nullptr;
};

} // namespace kernel
Expand Down
6 changes: 1 addition & 5 deletions runtime/vm/compiler/frontend/bytecode_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1020,13 +1020,9 @@ void BytecodeReaderHelper::ReadLocalVariables(const Bytecode& bytecode,
return;
}

intptr_t offset = reader_.ReadUInt();
USE(offset);

#if !defined(PRODUCT)
const intptr_t offset = reader_.ReadUInt();
bytecode.set_local_variables_binary_offset(
bytecode_component_->GetLocalVariablesOffset() + offset);
#endif
}

RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
Expand Down
3 changes: 1 addition & 2 deletions runtime/vm/compiler/frontend/bytecode_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,6 @@ class BytecodeSourcePositionsIterator : ValueObject {
bool is_yield_point_ = false;
};

#if !defined(PRODUCT)
class BytecodeLocalVariablesIterator : ValueObject {
public:
// These constants should match corresponding constants in
Expand Down Expand Up @@ -465,6 +464,7 @@ class BytecodeLocalVariablesIterator : ValueObject {
return true;
}

bool IsDone() const { return entries_remaining_ == 0; }
intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
bool IsScope() const { return Kind() == kScope; }
bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
Expand Down Expand Up @@ -522,7 +522,6 @@ class BytecodeLocalVariablesIterator : ValueObject {
TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource;
TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource;
};
#endif // !defined(PRODUCT)

bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
Zone* zone);
Expand Down
2 changes: 0 additions & 2 deletions runtime/vm/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15212,9 +15212,7 @@ RawBytecode* Bytecode::New(uword instructions,
result.set_pc_descriptors(Object::empty_descriptors());
result.set_instructions_binary_offset(instructions_offset);
result.set_source_positions_binary_offset(0);
#if !defined(PRODUCT)
result.set_local_variables_binary_offset(0);
#endif
}
return result.raw();
}
Expand Down
2 changes: 0 additions & 2 deletions runtime/vm/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -5807,7 +5807,6 @@ class Bytecode : public Object {
return (source_positions_binary_offset() != 0);
}

#if !defined(PRODUCT)
intptr_t local_variables_binary_offset() const {
return raw_ptr()->local_variables_binary_offset_;
}
Expand All @@ -5817,7 +5816,6 @@ class Bytecode : public Object {
bool HasLocalVariablesInfo() const {
return (local_variables_binary_offset() != 0);
}
#endif // !defined(PRODUCT)

RawLocalVarDescriptors* var_descriptors() const {
#if defined(PRODUCT)
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/raw_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -1423,7 +1423,7 @@ class RawBytecode : public RawObject {

int32_t instructions_binary_offset_;
int32_t source_positions_binary_offset_;
NOT_IN_PRODUCT(int32_t local_variables_binary_offset_);
int32_t local_variables_binary_offset_;

static bool ContainsPC(RawObject* raw_obj, uword pc);

Expand Down

0 comments on commit ef2a21f

Please sign in to comment.