| Index: runtime/vm/kernel_to_il.cc
|
| diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
|
| index e1251535705c70a0680a041c6a93efe8cda51b43..f2f505508259ef8df905379a08cab529e5f0c766 100644
|
| --- a/runtime/vm/kernel_to_il.cc
|
| +++ b/runtime/vm/kernel_to_il.cc
|
| @@ -1328,7 +1328,6 @@ const Array& TranslationHelper::ArgumentNames(List<NamedExpression>* named) {
|
| return names;
|
| }
|
|
|
| -
|
| ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder,
|
| Zone* zone,
|
| TranslationHelper* h,
|
| @@ -2067,7 +2066,8 @@ Fragment FlowGraphBuilder::PushContext(int size) {
|
| LocalVariable* context = MakeTemporary();
|
| instructions += LoadLocal(context);
|
| instructions += LoadLocal(parsed_function_->current_context_var());
|
| - instructions += StoreInstanceField(Context::parent_offset());
|
| + instructions +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Context::parent_offset());
|
| instructions += StoreLocal(TokenPosition::kNoSource,
|
| parsed_function_->current_context_var());
|
| ++context_depth_;
|
| @@ -2415,13 +2415,13 @@ Fragment FlowGraphBuilder::ThrowException(TokenPosition position) {
|
| }
|
|
|
|
|
| -Fragment FlowGraphBuilder::RethrowException(int catch_try_index) {
|
| +Fragment FlowGraphBuilder::RethrowException(TokenPosition position,
|
| + int catch_try_index) {
|
| Fragment instructions;
|
| instructions += Drop();
|
| instructions += Drop();
|
| instructions +=
|
| - Fragment(new (Z) ReThrowInstr(TokenPosition::kNoSource, catch_try_index))
|
| - .closed();
|
| + Fragment(new (Z) ReThrowInstr(position, catch_try_index)).closed();
|
| // Use it's side effect of leaving a constant on the stack (does not change
|
| // the graph).
|
| NullConstant();
|
| @@ -2548,11 +2548,8 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) {
|
| Value* value = Pop();
|
| ASSERT(stack_ == NULL);
|
|
|
| - const Function& function = parsed_function_->function();
|
| - if (FLAG_support_debugger && position.IsDebugPause() &&
|
| - !function.is_native()) {
|
| - instructions <<=
|
| - new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall);
|
| + if (NeedsDebugStepCheck(parsed_function_->function(), position)) {
|
| + instructions += DebugStepCheck(position);
|
| }
|
|
|
| ReturnInstr* return_instr = new (Z) ReturnInstr(position, value);
|
| @@ -2670,6 +2667,7 @@ Fragment FlowGraphBuilder::StoreInstanceFieldGuarded(
|
|
|
|
|
| Fragment FlowGraphBuilder::StoreInstanceField(
|
| + TokenPosition position,
|
| intptr_t offset,
|
| StoreBarrierType emit_store_barrier) {
|
| Value* value = Pop();
|
| @@ -2677,7 +2675,7 @@ Fragment FlowGraphBuilder::StoreInstanceField(
|
| emit_store_barrier = kNoStoreBarrier;
|
| }
|
| StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
|
| - offset, Pop(), value, emit_store_barrier, TokenPosition::kNoSource);
|
| + offset, Pop(), value, emit_store_barrier, position);
|
| return Fragment(store);
|
| }
|
|
|
| @@ -2689,21 +2687,10 @@ Fragment FlowGraphBuilder::StoreLocal(TokenPosition position,
|
| LocalVariable* value = MakeTemporary();
|
| instructions += LoadContextAt(variable->owner()->context_level());
|
| instructions += LoadLocal(value);
|
| - instructions +=
|
| - StoreInstanceField(Context::variable_offset(variable->index()));
|
| + instructions += StoreInstanceField(
|
| + position, Context::variable_offset(variable->index()));
|
| } else {
|
| Value* value = Pop();
|
| - if (FLAG_support_debugger && position.IsDebugPause() &&
|
| - !variable->IsInternal()) {
|
| - if (value->definition()->IsConstant() ||
|
| - value->definition()->IsAllocateObject() ||
|
| - (value->definition()->IsLoadLocal() &&
|
| - !value->definition()->AsLoadLocal()->local().IsInternal())) {
|
| - instructions <<= new (Z)
|
| - DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall);
|
| - }
|
| - }
|
| -
|
| StoreLocalInstr* store =
|
| new (Z) StoreLocalInstr(*variable, value, position);
|
| instructions <<= store;
|
| @@ -2713,9 +2700,10 @@ Fragment FlowGraphBuilder::StoreLocal(TokenPosition position,
|
| }
|
|
|
|
|
| -Fragment FlowGraphBuilder::StoreStaticField(const dart::Field& field) {
|
| - return Fragment(new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(),
|
| - TokenPosition::kNoSource));
|
| +Fragment FlowGraphBuilder::StoreStaticField(TokenPosition position,
|
| + const dart::Field& field) {
|
| + return Fragment(
|
| + new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(), position));
|
| }
|
|
|
|
|
| @@ -3086,7 +3074,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
| // eligible for garbage collection.
|
| body += LoadLocal(context);
|
| body += LoadLocal(parameter);
|
| - body += StoreInstanceField(Context::variable_offset(variable->index()));
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + Context::variable_offset(variable->index()));
|
| body += NullConstant();
|
| body += StoreLocal(TokenPosition::kNoSource, parameter);
|
| body += Drop();
|
| @@ -3227,7 +3216,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
| // which acts like an anchor, so we need to skip it.
|
| then->LinkTo(yield_continuations_[i].entry->next());
|
| then->set_try_index(yield_continuations_[i].try_index);
|
| -
|
| // False branch will contain the next comparison.
|
| dispatch = Fragment(dispatch.entry, otherwise);
|
| block = otherwise;
|
| @@ -3237,8 +3225,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
| context_depth_ = current_context_depth;
|
| }
|
|
|
| - if (FLAG_support_debugger && function->position().IsDebugPause() &&
|
| - !dart_function.is_native() && dart_function.is_debuggable()) {
|
| + if (NeedsDebugStepCheck(dart_function, function->position())) {
|
| // If a switch was added above: Start the switch by injecting a debugable
|
| // safepoint so stepping over an await works.
|
| // If not, still start the body with a debugable safepoint to ensure
|
| @@ -3258,9 +3245,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
| check_pos = function->position();
|
| ASSERT(check_pos.IsDebugPause());
|
| }
|
| - Fragment check(
|
| - new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall));
|
| - body = check + body;
|
| + body = DebugStepCheck(check_pos) + body;
|
| }
|
|
|
| normal_entry->LinkTo(body.entry);
|
| @@ -3365,7 +3350,8 @@ Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
|
| body += LoadLocal(scopes_->this_variable);
|
| body += LoadLocal(
|
| LookupVariable(kernel_function->positional_parameters()[0]));
|
| - body += StoreInstanceField(LinkedHashMap::index_offset());
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + LinkedHashMap::index_offset());
|
| body += NullConstant();
|
| break;
|
| case MethodRecognizer::kLinkedHashMap_getData:
|
| @@ -3377,7 +3363,8 @@ Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
|
| body += LoadLocal(scopes_->this_variable);
|
| body += LoadLocal(
|
| LookupVariable(kernel_function->positional_parameters()[0]));
|
| - body += StoreInstanceField(LinkedHashMap::data_offset());
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + LinkedHashMap::data_offset());
|
| body += NullConstant();
|
| break;
|
| case MethodRecognizer::kLinkedHashMap_getHashMask:
|
| @@ -3389,7 +3376,8 @@ Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
|
| body += LoadLocal(scopes_->this_variable);
|
| body += LoadLocal(
|
| LookupVariable(kernel_function->positional_parameters()[0]));
|
| - body += StoreInstanceField(LinkedHashMap::hash_mask_offset(),
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + LinkedHashMap::hash_mask_offset(),
|
| kNoStoreBarrier);
|
| body += NullConstant();
|
| break;
|
| @@ -3402,7 +3390,8 @@ Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
|
| body += LoadLocal(scopes_->this_variable);
|
| body += LoadLocal(
|
| LookupVariable(kernel_function->positional_parameters()[0]));
|
| - body += StoreInstanceField(LinkedHashMap::used_data_offset(),
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + LinkedHashMap::used_data_offset(),
|
| kNoStoreBarrier);
|
| body += NullConstant();
|
| break;
|
| @@ -3415,7 +3404,8 @@ Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
|
| body += LoadLocal(scopes_->this_variable);
|
| body += LoadLocal(
|
| LookupVariable(kernel_function->positional_parameters()[0]));
|
| - body += StoreInstanceField(LinkedHashMap::deleted_keys_offset(),
|
| + body += StoreInstanceField(TokenPosition::kNoSource,
|
| + LinkedHashMap::deleted_keys_offset(),
|
| kNoStoreBarrier);
|
| body += NullConstant();
|
| break;
|
| @@ -3456,7 +3446,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
|
| body += StoreInstanceFieldGuarded(field, false);
|
| } else {
|
| body += LoadLocal(setter_value);
|
| - body += StoreStaticField(field);
|
| + body += StoreStaticField(TokenPosition::kNoSource, field);
|
| }
|
| body += NullConstant();
|
| } else if (is_method) {
|
| @@ -3525,17 +3515,20 @@ Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
|
| // Store the function and the context in the closure.
|
| fragment += LoadLocal(closure);
|
| fragment += Constant(target);
|
| - fragment += StoreInstanceField(Closure::function_offset());
|
| + fragment +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
|
|
|
| fragment += LoadLocal(closure);
|
| fragment += LoadLocal(context);
|
| - fragment += StoreInstanceField(Closure::context_offset());
|
| + fragment +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
|
|
|
| // The context is on top of the operand stack. Store `this`. The context
|
| // doesn't need a parent pointer because it doesn't close over anything
|
| // else.
|
| fragment += LoadLocal(scopes_->this_variable);
|
| - fragment += StoreInstanceField(Context::variable_offset(0));
|
| + fragment +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Context::variable_offset(0));
|
|
|
| return fragment;
|
| }
|
| @@ -3567,6 +3560,31 @@ Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
|
| }
|
|
|
|
|
| +bool FlowGraphBuilder::NeedsDebugStepCheck(const Function& function,
|
| + TokenPosition position) {
|
| + return FLAG_support_debugger && position.IsDebugPause() &&
|
| + !function.is_native() && function.is_debuggable();
|
| +}
|
| +
|
| +
|
| +bool FlowGraphBuilder::NeedsDebugStepCheck(Value* value,
|
| + TokenPosition position) {
|
| + if (!FLAG_support_debugger || !position.IsDebugPause()) return false;
|
| + Definition* definition = value->definition();
|
| + if (definition->IsConstant() || definition->IsLoadStaticField()) return true;
|
| + if (definition->IsAllocateObject()) {
|
| + return !definition->AsAllocateObject()->closure_function().IsNull();
|
| + }
|
| + return definition->IsLoadLocal() &&
|
| + !definition->AsLoadLocal()->local().IsInternal();
|
| +}
|
| +
|
| +Fragment FlowGraphBuilder::DebugStepCheck(TokenPosition position) {
|
| + return Fragment(
|
| + new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall));
|
| +}
|
| +
|
| +
|
| Fragment FlowGraphBuilder::EvaluateAssertion() {
|
| const dart::Class& klass = dart::Class::ZoneHandle(
|
| Z, dart::Library::LookupCoreClass(Symbols::AssertionError()));
|
| @@ -4483,6 +4501,9 @@ void FlowGraphBuilder::VisitVariableGet(VariableGet* node) {
|
|
|
| void FlowGraphBuilder::VisitVariableSet(VariableSet* node) {
|
| Fragment instructions = TranslateExpression(node->expression());
|
| + if (NeedsDebugStepCheck(stack_, node->position())) {
|
| + instructions = DebugStepCheck(node->position()) + instructions;
|
| + }
|
| instructions += CheckVariableTypeInCheckedMode(node->variable());
|
| instructions +=
|
| StoreLocal(node->position(), LookupVariable(node->variable()));
|
| @@ -4535,11 +4556,14 @@ void FlowGraphBuilder::VisitStaticSet(StaticSet* node) {
|
| dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field));
|
| const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
|
| Fragment instructions = TranslateExpression(node->expression());
|
| + if (NeedsDebugStepCheck(stack_, node->position())) {
|
| + instructions = DebugStepCheck(node->position()) + instructions;
|
| + }
|
| instructions += CheckAssignableInCheckedMode(
|
| dst_type, dart::String::ZoneHandle(Z, field.name()));
|
| LocalVariable* variable = MakeTemporary();
|
| instructions += LoadLocal(variable);
|
| - fragment_ = instructions + StoreStaticField(field);
|
| + fragment_ = instructions + StoreStaticField(node->position(), field);
|
| } else {
|
| ASSERT(target->IsProcedure());
|
|
|
| @@ -4965,8 +4989,8 @@ void FlowGraphBuilder::VisitAsExpression(AsExpression* node) {
|
| instructions += PushArgument(); // Type.
|
|
|
| instructions += InstanceCall(
|
| - TokenPosition::kNoSource,
|
| - dart::Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, 3);
|
| + node->position(), dart::Library::PrivateCoreLibName(Symbols::_as()),
|
| + Token::kAS, 3);
|
| }
|
|
|
| fragment_ = instructions;
|
| @@ -5190,6 +5214,9 @@ void FlowGraphBuilder::VisitThrow(Throw* node) {
|
| Fragment instructions;
|
|
|
| instructions += TranslateExpression(node->expression());
|
| + if (NeedsDebugStepCheck(stack_, node->position())) {
|
| + instructions = DebugStepCheck(node->position()) + instructions;
|
| + }
|
| instructions += PushArgument();
|
| instructions += ThrowException(node->position());
|
| ASSERT(instructions.is_closed());
|
| @@ -5201,11 +5228,13 @@ void FlowGraphBuilder::VisitThrow(Throw* node) {
|
| void FlowGraphBuilder::VisitRethrow(Rethrow* node) {
|
| Fragment instructions;
|
|
|
| + instructions = DebugStepCheck(node->position()) + instructions;
|
| instructions += LoadLocal(catch_block_->exception_var());
|
| instructions += PushArgument();
|
| instructions += LoadLocal(catch_block_->stack_trace_var());
|
| instructions += PushArgument();
|
| - instructions += RethrowException(catch_block_->catch_try_index());
|
| + instructions +=
|
| + RethrowException(node->position(), catch_block_->catch_try_index());
|
|
|
| fragment_ = instructions;
|
| }
|
| @@ -5268,13 +5297,17 @@ void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* node) {
|
| if (instructions.is_open()) {
|
| if (inside_try_finally) {
|
| ASSERT(scopes_->finally_return_variable != NULL);
|
| - instructions += StoreLocal(TokenPosition::kNoSource,
|
| - scopes_->finally_return_variable);
|
| + const Function& function = parsed_function_->function();
|
| + if (NeedsDebugStepCheck(function, node->position())) {
|
| + instructions += DebugStepCheck(node->position());
|
| + }
|
| + instructions +=
|
| + StoreLocal(node->position(), scopes_->finally_return_variable);
|
| instructions += Drop();
|
| instructions += TranslateFinallyFinalizers(NULL, -1);
|
| if (instructions.is_open()) {
|
| instructions += LoadLocal(scopes_->finally_return_variable);
|
| - instructions += Return(node->position());
|
| + instructions += Return(TokenPosition::kNoSource);
|
| }
|
| } else {
|
| instructions += Return(node->position());
|
| @@ -5311,16 +5344,24 @@ void FlowGraphBuilder::VisitVariableDeclaration(VariableDeclaration* node) {
|
| instructions += CheckVariableTypeInCheckedMode(node);
|
| }
|
| }
|
| - instructions += StoreLocal(variable->token_pos(), variable);
|
| + // Use position of equal sign if it exists. If the equal sign does not exist
|
| + // use the position of the identifier.
|
| + TokenPosition debug_position =
|
| + Utils::Maximum(node->position(), node->equals_position());
|
| + if (NeedsDebugStepCheck(stack_, debug_position)) {
|
| + instructions = DebugStepCheck(debug_position) + instructions;
|
| + }
|
| + instructions += StoreLocal(node->position(), variable);
|
| instructions += Drop();
|
| fragment_ = instructions;
|
| }
|
|
|
|
|
| void FlowGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) {
|
| - Fragment instructions = TranslateFunctionNode(node->function(), node);
|
| + Fragment instructions = DebugStepCheck(node->position());
|
| + instructions += TranslateFunctionNode(node->function(), node);
|
| instructions +=
|
| - StoreLocal(TokenPosition::kNoSource, LookupVariable(node->variable()));
|
| + StoreLocal(node->position(), LookupVariable(node->variable()));
|
| instructions += Drop();
|
| fragment_ = instructions;
|
| }
|
| @@ -5559,6 +5600,9 @@ void FlowGraphBuilder::VisitBreakStatement(BreakStatement* node) {
|
| instructions +=
|
| TranslateFinallyFinalizers(outer_finally, target_context_depth);
|
| if (instructions.is_open()) {
|
| + if (NeedsDebugStepCheck(parsed_function_->function(), node->position())) {
|
| + instructions += DebugStepCheck(node->position());
|
| + }
|
| instructions += Goto(destination);
|
| }
|
| fragment_ = instructions;
|
| @@ -5901,7 +5945,8 @@ void FlowGraphBuilder::VisitTryFinally(TryFinally* node) {
|
| finally_body += PushArgument();
|
| finally_body += LoadLocal(CurrentStackTrace());
|
| finally_body += PushArgument();
|
| - finally_body += RethrowException(try_handler_index);
|
| + finally_body +=
|
| + RethrowException(TokenPosition::kNoSource, try_handler_index);
|
| Drop();
|
| }
|
| --catch_depth_;
|
| @@ -6012,7 +6057,7 @@ void FlowGraphBuilder::VisitTryCatch(class TryCatch* node) {
|
| catch_body += PushArgument();
|
| catch_body += LoadLocal(CurrentStackTrace());
|
| catch_body += PushArgument();
|
| - catch_body += RethrowException(try_handler_index);
|
| + catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
|
| Drop();
|
| }
|
| --catch_depth_;
|
| @@ -6087,7 +6132,8 @@ void FlowGraphBuilder::VisitYieldStatement(YieldStatement* node) {
|
| rethrow += PushArgument();
|
| rethrow += LoadLocal(stack_trace_var);
|
| rethrow += PushArgument();
|
| - rethrow += RethrowException(CatchClauseNode::kInvalidTryIndex);
|
| + rethrow += RethrowException(TokenPosition::kNoSource,
|
| + CatchClauseNode::kInvalidTryIndex);
|
| Drop();
|
|
|
|
|
| @@ -6164,11 +6210,13 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node,
|
| // Store the function and the context in the closure.
|
| instructions += LoadLocal(closure);
|
| instructions += Constant(function);
|
| - instructions += StoreInstanceField(Closure::function_offset());
|
| + instructions +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
|
|
|
| instructions += LoadLocal(closure);
|
| instructions += LoadLocal(parsed_function_->current_context_var());
|
| - instructions += StoreInstanceField(Closure::context_offset());
|
| + instructions +=
|
| + StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
|
|
|
| return instructions;
|
| }
|
|
|