b0a71d364c
#if defined(DART_PRECOMPILED_RUNTIME) #error "AOT runtime should not use compiler sources (including header files)" #endif // defined(DART_PRECOMPILED_RUNTIME) Remove #if defined(DART_PRECOMPILED_RUNTIME) from most compiler sources. Change-Id: Id175c83fdbea38d9d5e1371ff433e3888f2afe8a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/143523 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
253 lines
8.7 KiB
C++
253 lines
8.7 KiB
C++
// Copyright (c) 2018, 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.
|
|
|
|
#ifndef RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
|
|
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
|
|
|
|
#if defined(DART_PRECOMPILED_RUNTIME)
|
|
#error "AOT runtime should not use compiler sources (including header files)"
|
|
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
#include "vm/compiler/backend/il.h"
|
|
#include "vm/compiler/frontend/base_flow_graph_builder.h"
|
|
#include "vm/compiler/frontend/kernel_translation_helper.h" // For InferredTypeMetadata
|
|
#include "vm/constants_kbc.h"
|
|
|
|
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).
|
|
// TODO(alexmarkov): extend this class and IL to generate an interpreter in
|
|
// addition to compiling bytecode.
|
|
class BytecodeFlowGraphBuilder {
|
|
public:
|
|
BytecodeFlowGraphBuilder(BaseFlowGraphBuilder* flow_graph_builder,
|
|
ParsedFunction* parsed_function,
|
|
ZoneGrowableArray<const ICData*>* ic_data_array)
|
|
: flow_graph_builder_(flow_graph_builder),
|
|
zone_(flow_graph_builder->zone_),
|
|
is_generating_interpreter_(
|
|
false), // TODO(alexmarkov): pass as argument
|
|
parsed_function_(parsed_function),
|
|
ic_data_array_(ic_data_array),
|
|
object_pool_(ObjectPool::Handle(zone_)),
|
|
bytecode_length_(0),
|
|
pc_(0),
|
|
position_(TokenPosition::kNoSource),
|
|
local_vars_(zone_, 0),
|
|
parameters_(zone_, 0),
|
|
exception_var_(nullptr),
|
|
stacktrace_var_(nullptr),
|
|
scratch_var_(nullptr),
|
|
prologue_info_(-1, -1),
|
|
throw_no_such_method_(nullptr),
|
|
inferred_types_attribute_(Array::Handle(zone_)) {}
|
|
|
|
FlowGraph* BuildGraph();
|
|
|
|
// Create parameter variables without building a flow graph.
|
|
void CreateParameterVariables();
|
|
|
|
protected:
|
|
// Returns `true` if building a flow graph for a bytecode interpreter, or
|
|
// `false` if compiling a function from bytecode.
|
|
bool is_generating_interpreter() const { return is_generating_interpreter_; }
|
|
|
|
private:
|
|
// Operand of bytecode instruction, either intptr_t value (if compiling
|
|
// bytecode) or Definition (if generating interpreter).
|
|
class Operand {
|
|
public:
|
|
explicit Operand(Definition* definition)
|
|
: definition_(definition), value_(0) {
|
|
ASSERT(definition != nullptr);
|
|
}
|
|
|
|
explicit Operand(intptr_t value) : definition_(nullptr), value_(value) {}
|
|
|
|
Definition* definition() const {
|
|
ASSERT(definition_ != nullptr);
|
|
return definition_;
|
|
}
|
|
|
|
intptr_t value() const {
|
|
ASSERT(definition_ == nullptr);
|
|
return value_;
|
|
}
|
|
|
|
private:
|
|
Definition* definition_;
|
|
intptr_t value_;
|
|
};
|
|
|
|
// Constant from a constant pool.
|
|
// It is either Object (if compiling bytecode) or Definition
|
|
// (if generating interpreter).
|
|
class Constant {
|
|
public:
|
|
explicit Constant(Definition* definition)
|
|
: definition_(definition), value_(Object::null_object()) {
|
|
ASSERT(definition != nullptr);
|
|
}
|
|
|
|
explicit Constant(Zone* zone, const Object& value)
|
|
: definition_(nullptr), value_(value) {}
|
|
|
|
Definition* definition() const {
|
|
ASSERT(definition_ != nullptr);
|
|
return definition_;
|
|
}
|
|
|
|
const Object& value() const {
|
|
ASSERT(definition_ == nullptr);
|
|
return value_;
|
|
}
|
|
|
|
private:
|
|
Definition* definition_;
|
|
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();
|
|
Operand DecodeOperandD();
|
|
Operand DecodeOperandE();
|
|
Operand DecodeOperandF();
|
|
Operand DecodeOperandX();
|
|
Operand DecodeOperandY();
|
|
Operand DecodeOperandT();
|
|
Constant ConstantAt(Operand entry_index, intptr_t add_index = 0);
|
|
void PushConstant(Constant constant);
|
|
Constant PopConstant();
|
|
void LoadStackSlots(intptr_t num_slots);
|
|
void AllocateLocalVariables(Operand frame_size,
|
|
intptr_t num_param_locals = 0);
|
|
LocalVariable* AllocateParameter(intptr_t param_index,
|
|
VariableIndex var_index);
|
|
void AllocateFixedParameters();
|
|
|
|
// Allocates parameters and local variables in case of EntryOptional.
|
|
// Returns pointer to the instruction after EntryOptional/LoadConstant/Frame
|
|
// bytecodes.
|
|
const KBCInstr* AllocateParametersAndLocalsForEntryOptional();
|
|
|
|
LocalVariable* LocalVariableAt(intptr_t local_index);
|
|
void StoreLocal(Operand local_index);
|
|
void LoadLocal(Operand local_index);
|
|
Value* Pop();
|
|
intptr_t GetStackDepth() const;
|
|
bool IsStackEmpty() const;
|
|
InferredTypeMetadata GetInferredType(intptr_t pc);
|
|
void PropagateStackState(intptr_t target_pc);
|
|
void DropUnusedValuesFromStack();
|
|
void BuildJumpIfStrictCompare(Token::Kind cmp_kind);
|
|
void BuildPrimitiveOp(const String& name,
|
|
Token::Kind token_kind,
|
|
const AbstractType& static_receiver_type,
|
|
int num_args);
|
|
void BuildIntOp(const String& name, Token::Kind token_kind, int num_args);
|
|
void BuildDoubleOp(const String& name, Token::Kind token_kind, int num_args);
|
|
void BuildDirectCallCommon(bool is_unchecked_call);
|
|
void BuildInterfaceCallCommon(bool is_unchecked_call,
|
|
bool is_instantiated_call);
|
|
|
|
void BuildInstruction(KernelBytecode::Opcode opcode);
|
|
void BuildFfiAsFunction();
|
|
void BuildFfiNativeCallbackFunction();
|
|
void BuildDebugStepCheck();
|
|
|
|
#define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3) \
|
|
void Build##name();
|
|
KERNEL_BYTECODES_LIST(DECLARE_BUILD_METHOD)
|
|
#undef DECLARE_BUILD_METHOD
|
|
|
|
intptr_t GetTryIndex(const PcDescriptors& descriptors, intptr_t pc);
|
|
JoinEntryInstr* EnsureControlFlowJoin(const PcDescriptors& descriptors,
|
|
intptr_t pc);
|
|
bool RequiresScratchVar(const KBCInstr* instr);
|
|
void CollectControlFlow(const PcDescriptors& descriptors,
|
|
const ExceptionHandlers& handlers,
|
|
GraphEntryInstr* graph_entry);
|
|
|
|
// 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(
|
|
const KBCInstr* jump_if_unchecked);
|
|
|
|
Thread* thread() const { return flow_graph_builder_->thread_; }
|
|
Isolate* isolate() const { return thread()->isolate(); }
|
|
|
|
ParsedFunction* parsed_function() const {
|
|
ASSERT(!is_generating_interpreter());
|
|
return parsed_function_;
|
|
}
|
|
const Function& function() const { return parsed_function()->function(); }
|
|
|
|
BaseFlowGraphBuilder* flow_graph_builder_;
|
|
Zone* zone_;
|
|
bool is_generating_interpreter_;
|
|
|
|
// The following members are available only when compiling bytecode.
|
|
|
|
ParsedFunction* parsed_function_;
|
|
ZoneGrowableArray<const ICData*>* ic_data_array_;
|
|
ObjectPool& object_pool_;
|
|
const KBCInstr* raw_bytecode_ = nullptr;
|
|
intptr_t bytecode_length_;
|
|
intptr_t pc_;
|
|
intptr_t next_pc_ = -1;
|
|
const KBCInstr* bytecode_instr_ = nullptr;
|
|
TokenPosition position_;
|
|
intptr_t last_yield_point_pc_ = 0;
|
|
intptr_t last_yield_point_index_ = 0;
|
|
Fragment code_;
|
|
ZoneGrowableArray<LocalVariable*> local_vars_;
|
|
ZoneGrowableArray<LocalVariable*> parameters_;
|
|
LocalVariable* exception_var_;
|
|
LocalVariable* stacktrace_var_;
|
|
LocalVariable* scratch_var_;
|
|
IntMap<JoinEntryInstr*> jump_targets_;
|
|
IntMap<Value*> stack_states_;
|
|
PrologueInfo prologue_info_;
|
|
JoinEntryInstr* throw_no_such_method_;
|
|
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;
|
|
Array& inferred_types_attribute_;
|
|
intptr_t inferred_types_index_ = 0;
|
|
};
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
|