Index: runtime/vm/kernel_to_il.h |
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h |
index 524a13a61450b7e4da458615b9f41f4482019ca8..ae0db180c64fcf424319616ce136a4bf86aee3d3 100644 |
--- a/runtime/vm/kernel_to_il.h |
+++ b/runtime/vm/kernel_to_il.h |
@@ -347,9 +347,11 @@ class TranslationHelper { |
const dart::String& DartSetterName(NameIndex setter); |
const dart::String& DartSetterName(Name* setter_name); |
+ const dart::String& DartSetterName(NameIndex parent, StringIndex setter); |
const dart::String& DartGetterName(NameIndex getter); |
const dart::String& DartGetterName(Name* getter_name); |
+ const dart::String& DartGetterName(NameIndex parent, StringIndex getter); |
const dart::String& DartFieldName(Name* kernel_name); |
@@ -357,6 +359,7 @@ class TranslationHelper { |
const dart::String& DartMethodName(NameIndex method); |
const dart::String& DartMethodName(Name* method_name); |
+ const dart::String& DartMethodName(NameIndex parent, StringIndex method); |
const dart::String& DartFactoryName(NameIndex factory); |
@@ -389,9 +392,6 @@ class TranslationHelper { |
dart::String* name_to_modify, |
bool symbolize = true); |
- const dart::String& DartSetterName(NameIndex parent, StringIndex setter); |
- const dart::String& DartGetterName(NameIndex parent, StringIndex getter); |
- const dart::String& DartMethodName(NameIndex parent, StringIndex method); |
Thread* thread_; |
Zone* zone_; |
@@ -770,6 +770,17 @@ class ScopeBuilder : public RecursiveVisitor { |
bool needs_expr_temp_; |
}; |
+struct YieldContinuation { |
+ Instruction* entry; |
+ intptr_t try_index; |
+ |
+ YieldContinuation(Instruction* entry, intptr_t try_index) |
+ : entry(entry), try_index(try_index) {} |
+ |
+ YieldContinuation() |
+ : entry(NULL), try_index(CatchClauseNode::kInvalidTryIndex) {} |
+}; |
+ |
class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
public: |
FlowGraphBuilder(TreeNode* node, |
@@ -880,7 +891,9 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
Fragment TranslateFunctionNode(FunctionNode* node, TreeNode* parent); |
Fragment EnterScope(TreeNode* node, bool* new_context = NULL); |
+ Fragment EnterScope(intptr_t kernel_offset, bool* new_context = NULL); |
Fragment ExitScope(TreeNode* node); |
+ Fragment ExitScope(intptr_t kernel_offset); |
Fragment LoadContextAt(int depth); |
Fragment AdjustContextTo(int depth); |
@@ -983,6 +996,8 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
Fragment EvaluateAssertion(); |
Fragment CheckReturnTypeInCheckedMode(); |
Fragment CheckVariableTypeInCheckedMode(VariableDeclaration* variable); |
+ Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type, |
+ const dart::String& name_symbol); |
Fragment CheckBooleanInCheckedMode(); |
Fragment CheckAssignableInCheckedMode(const dart::AbstractType& dst_type, |
const dart::String& dst_name); |
@@ -1012,6 +1027,7 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
LocalVariable* variable, |
intptr_t pos); |
dart::LocalVariable* LookupVariable(VariableDeclaration* var); |
+ dart::LocalVariable* LookupVariable(intptr_t kernel_offset); |
void SetTempIndex(Definition* definition); |
@@ -1056,17 +1072,6 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
ScopeBuildingResult* scopes_; |
- struct YieldContinuation { |
- Instruction* entry; |
- intptr_t try_index; |
- |
- YieldContinuation(Instruction* entry, intptr_t try_index) |
- : entry(entry), try_index(try_index) {} |
- |
- YieldContinuation() |
- : entry(NULL), try_index(CatchClauseNode::kInvalidTryIndex) {} |
- }; |
- |
GrowableArray<YieldContinuation> yield_continuations_; |
LocalVariable* CurrentException() { |
@@ -1119,6 +1124,199 @@ class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor { |
}; |
+class SwitchBlock { |
+ public: |
+ SwitchBlock(FlowGraphBuilder* builder, intptr_t num_cases) |
+ : builder_(builder), |
+ outer_(builder->switch_block_), |
+ outer_finally_(builder->try_finally_block_), |
+ num_cases_(num_cases), |
+ context_depth_(builder->context_depth_), |
+ try_index_(builder->CurrentTryIndex()) { |
+ builder_->switch_block_ = this; |
+ if (outer_ != NULL) { |
+ depth_ = outer_->depth_ + outer_->num_cases_; |
+ } else { |
+ depth_ = 0; |
+ } |
+ } |
+ ~SwitchBlock() { builder_->switch_block_ = outer_; } |
+ |
+ bool HadJumper(intptr_t case_num) { |
+ return destinations_.Lookup(case_num) != NULL; |
+ } |
+ |
+ // Get destination via absolute target number (i.e. the correct destination |
+ // is not not necessarily in this block. |
+ JoinEntryInstr* Destination(intptr_t target_index, |
+ TryFinallyBlock** outer_finally = NULL, |
+ intptr_t* context_depth = NULL) { |
+ // Find corresponding [SwitchStatement]. |
+ SwitchBlock* block = this; |
+ while (block->depth_ > target_index) { |
+ block = block->outer_; |
+ } |
+ |
+ // Set the outer finally block. |
+ if (outer_finally != NULL) { |
+ *outer_finally = block->outer_finally_; |
+ *context_depth = block->context_depth_; |
+ } |
+ |
+ // Ensure there's [JoinEntryInstr] for that [SwitchCase]. |
+ return block->EnsureDestination(target_index - block->depth_); |
+ } |
+ |
+ // Get destination via relative target number (i.e. relative to this block, |
+ // 0 is first case in this block etc). |
+ JoinEntryInstr* DestinationDirect(intptr_t case_num, |
+ TryFinallyBlock** outer_finally = NULL, |
+ intptr_t* context_depth = NULL) { |
+ // Set the outer finally block. |
+ if (outer_finally != NULL) { |
+ *outer_finally = outer_finally_; |
+ *context_depth = context_depth_; |
+ } |
+ |
+ // Ensure there's [JoinEntryInstr] for that [SwitchCase]. |
+ return EnsureDestination(case_num); |
+ } |
+ |
+ private: |
+ JoinEntryInstr* EnsureDestination(intptr_t case_num) { |
+ JoinEntryInstr* cached_inst = destinations_.Lookup(case_num); |
+ if (cached_inst == NULL) { |
+ JoinEntryInstr* inst = builder_->BuildJoinEntry(try_index_); |
+ destinations_.Insert(case_num, inst); |
+ return inst; |
+ } |
+ return cached_inst; |
+ } |
+ |
+ FlowGraphBuilder* builder_; |
+ SwitchBlock* outer_; |
+ |
+ IntMap<JoinEntryInstr*> destinations_; |
+ |
+ TryFinallyBlock* outer_finally_; |
+ intptr_t num_cases_; |
+ intptr_t depth_; |
+ intptr_t context_depth_; |
+ intptr_t try_index_; |
+}; |
+ |
+ |
+class TryCatchBlock { |
+ public: |
+ explicit TryCatchBlock(FlowGraphBuilder* builder, |
+ intptr_t try_handler_index = -1) |
+ : builder_(builder), |
+ outer_(builder->try_catch_block_), |
+ try_index_(try_handler_index) { |
+ if (try_index_ == -1) try_index_ = builder->AllocateTryIndex(); |
+ builder->try_catch_block_ = this; |
+ } |
+ ~TryCatchBlock() { builder_->try_catch_block_ = outer_; } |
+ |
+ intptr_t try_index() { return try_index_; } |
+ TryCatchBlock* outer() const { return outer_; } |
+ |
+ private: |
+ FlowGraphBuilder* builder_; |
+ TryCatchBlock* outer_; |
+ intptr_t try_index_; |
+}; |
+ |
+ |
+class TryFinallyBlock { |
+ public: |
+ TryFinallyBlock(FlowGraphBuilder* builder, |
+ Statement* finalizer, |
+ intptr_t finalizer_kernel_offset) |
+ : builder_(builder), |
+ outer_(builder->try_finally_block_), |
+ finalizer_(finalizer), |
+ finalizer_kernel_offset_(finalizer_kernel_offset), |
+ context_depth_(builder->context_depth_), |
+ // Finalizers are executed outside of the try block hence |
+ // try depth of finalizers are one less than current try |
+ // depth. |
+ try_depth_(builder->try_depth_ - 1), |
+ try_index_(builder_->CurrentTryIndex()) { |
+ builder_->try_finally_block_ = this; |
+ } |
+ ~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } |
+ |
+ Statement* finalizer() const { return finalizer_; } |
+ intptr_t finalizer_kernel_offset() const { return finalizer_kernel_offset_; } |
+ intptr_t context_depth() const { return context_depth_; } |
+ intptr_t try_depth() const { return try_depth_; } |
+ intptr_t try_index() const { return try_index_; } |
+ TryFinallyBlock* outer() const { return outer_; } |
+ |
+ private: |
+ FlowGraphBuilder* const builder_; |
+ TryFinallyBlock* const outer_; |
+ Statement* const finalizer_; |
+ intptr_t finalizer_kernel_offset_; |
+ const intptr_t context_depth_; |
+ const intptr_t try_depth_; |
+ const intptr_t try_index_; |
+}; |
+ |
+ |
+class BreakableBlock { |
+ public: |
+ explicit BreakableBlock(FlowGraphBuilder* builder) |
+ : builder_(builder), |
+ outer_(builder->breakable_block_), |
+ destination_(NULL), |
+ outer_finally_(builder->try_finally_block_), |
+ context_depth_(builder->context_depth_), |
+ try_index_(builder->CurrentTryIndex()) { |
+ if (builder_->breakable_block_ == NULL) { |
+ index_ = 0; |
+ } else { |
+ index_ = builder_->breakable_block_->index_ + 1; |
+ } |
+ builder_->breakable_block_ = this; |
+ } |
+ ~BreakableBlock() { builder_->breakable_block_ = outer_; } |
+ |
+ bool HadJumper() { return destination_ != NULL; } |
+ |
+ JoinEntryInstr* destination() { return destination_; } |
+ |
+ JoinEntryInstr* BreakDestination(intptr_t label_index, |
+ TryFinallyBlock** outer_finally, |
+ intptr_t* context_depth) { |
+ BreakableBlock* block = builder_->breakable_block_; |
+ while (block->index_ != label_index) { |
+ block = block->outer_; |
+ } |
+ ASSERT(block != NULL); |
+ *outer_finally = block->outer_finally_; |
+ *context_depth = block->context_depth_; |
+ return block->EnsureDestination(); |
+ } |
+ |
+ private: |
+ JoinEntryInstr* EnsureDestination() { |
+ if (destination_ == NULL) { |
+ destination_ = builder_->BuildJoinEntry(try_index_); |
+ } |
+ return destination_; |
+ } |
+ |
+ FlowGraphBuilder* builder_; |
+ intptr_t index_; |
+ BreakableBlock* outer_; |
+ JoinEntryInstr* destination_; |
+ TryFinallyBlock* outer_finally_; |
+ intptr_t context_depth_; |
+ intptr_t try_index_; |
+}; |
+ |
class CatchBlock { |
public: |
CatchBlock(FlowGraphBuilder* builder, |