Chromium Code Reviews| Index: runtime/vm/kernel_binary_flowgraph.cc |
| diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc |
| index 37f596c4fa2535ec5c15ee3e6198bac1a1ef6388..09d338b82e816bbc3861ec2858acef21092dabe3 100644 |
| --- a/runtime/vm/kernel_binary_flowgraph.cc |
| +++ b/runtime/vm/kernel_binary_flowgraph.cc |
| @@ -121,6 +121,7 @@ ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() { |
| switch (function.kind()) { |
| case RawFunction::kClosureFunction: |
| + case RawFunction::kConvertedClosureFunction: |
| case RawFunction::kRegularFunction: |
| case RawFunction::kGetterFunction: |
| case RawFunction::kSetterFunction: |
| @@ -359,10 +360,10 @@ void StreamingScopeBuilder::VisitProcedure() { |
| void StreamingScopeBuilder::VisitField() { |
| builder_->ReadFieldUntilAnnotation( |
| &unused_nameindex, &unused_tokenposition, &unused_tokenposition, |
| - &unused_intptr, &unused_word); // read first part of field. |
| - builder_->SkipListOfExpressions(); // read annotations. |
| - VisitDartType(); // read type. |
| - Tag tag = builder_->ReadTag(); // read initializer (part 1). |
| + &unused_intptr, &unused_word); // read first part of field. |
| + builder_->SkipListOfExpressions(); // read annotations. |
| + VisitDartType(); // read type. |
| + Tag tag = builder_->ReadTag(); // read initializer (part 1). |
| if (tag == kSomething) { |
| VisitExpression(); // read initializer (part 2). |
| } |
| @@ -693,6 +694,26 @@ void StreamingScopeBuilder::VisitExpression() { |
| return; |
| case kNullLiteral: |
| return; |
| + case kVectorCreation: |
| + builder_->ReadUInt(); // read size. |
| + return; |
| + case kVectorGet: |
| + VisitExpression(); // read expression. |
| + builder_->ReadUInt(); // read index. |
| + return; |
| + case kVectorSet: |
| + VisitExpression(); // read vector expression. |
| + builder_->ReadUInt(); // read index. |
| + VisitExpression(); |
|
jensj
2017/06/19 10:41:54
A comment about what is read here would be nice.
Dmitry Stefantsov
2017/06/19 11:23:32
Agreed. I must have missed the spot. Thanks!
|
| + return; |
| + case kVectorCopy: |
| + VisitExpression(); // read vector expression. |
| + return; |
| + case kClosureCreation: |
| + builder_->SkipCanonicalNameReference(); // read function reference. |
| + VisitExpression(); // read context vector. |
| + VisitDartType(); // read function type of the closure. |
| + return; |
| default: |
| UNREACHABLE(); |
| } |
| @@ -1032,6 +1053,7 @@ void StreamingScopeBuilder::VisitDartType() { |
| case kDynamicType: |
| case kVoidType: |
| case kBottomType: |
| + case kVectorType: |
| // those contain nothing. |
| return; |
| case kInterfaceType: |
| @@ -1443,6 +1465,9 @@ void StreamingDartTypeTranslator::BuildTypeInternal() { |
| case kVoidType: |
| result_ = Object::void_type().raw(); |
| break; |
| + case kVectorType: |
| + result_ = Object::vector_type().raw(); |
| + break; |
| case kBottomType: |
| result_ = dart::Class::Handle(Z, I->object_store()->null_class()) |
| .CanonicalType(); |
| @@ -3141,6 +3166,83 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction( |
| flow_graph_builder_->next_block_id_ - 1); |
| } |
| + |
| +// This method follows the logic similar to that of |
| +// StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction. For |
| +// additional details on converted closure functions, please, see the comment on |
| +// the method Function::ConvertedClosureFunction. |
| +FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| + const Function& function) { |
| + const Function& target = Function::ZoneHandle(Z, function.parent_function()); |
| + |
| + TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); |
| + flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( |
| + *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId); |
| + SetupDefaultParameterValues(); |
| + |
| + Fragment body(normal_entry); |
| + body += flow_graph_builder_->CheckStackOverflowInPrologue(); |
| + |
| + // Load all the arguments. |
| + ASSERT(target.is_static()); |
| + |
| + TokenPosition end_position; |
| + ReadFunctionNodeUntilTypeParameters( |
| + &unused_tokenposition, &end_position, &unused_word, |
| + &unused_word); // read first part of function node. |
| + SkipTypeParametersList(); // read type parameter list. |
| + ReadUInt(); // read total parameter count. |
| + ReadUInt(); // read required_parameter_count. |
| + |
| + // Positional. |
| + intptr_t positional_argument_count = ReadListLength(); |
| + |
| + // The first argument is the instance of the closure class. For converted |
| + // closures its context field contains the context vector that is used by the |
| + // converted top-level function (target) explicitly and that should be passed |
| + // to that function as the first parameter. |
| + body += LoadLocal(LookupVariable(ReaderOffset())); // 0th variable offset. |
| + body += flow_graph_builder_->LoadField(Closure::context_offset()); |
| + body += PushArgument(); |
| + SkipVariableDeclaration(); // read 0th variable. |
| + |
| + // The rest of the parameters are the same for the method of the Closure class |
| + // being invoked and the top-level function (target). |
| + for (intptr_t i = 1; i < positional_argument_count; i++) { |
| + body += LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| + body += PushArgument(); |
| + SkipVariableDeclaration(); // read ith variable. |
| + } |
| + |
| + // Named. |
| + intptr_t named_argument_count = ReadListLength(); |
| + Array& argument_names = Array::ZoneHandle(Z); |
| + if (named_argument_count > 0) { |
| + argument_names = Array::New(named_argument_count); |
| + for (intptr_t i = 0; i < named_argument_count; i++) { |
| + body += |
| + LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| + body += PushArgument(); |
| + argument_names.SetAt( |
| + i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset()))); |
| + SkipVariableDeclaration(); // read ith variable. |
| + } |
| + } |
| + |
| + // Forward them to the target. |
| + intptr_t argument_count = positional_argument_count + named_argument_count; |
| + body += StaticCall(TokenPosition::kNoSource, target, argument_count, |
| + argument_names); |
| + |
| + // Return the result. |
| + body += Return(end_position); |
| + |
| + return new (Z) |
| + FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, |
| + flow_graph_builder_->next_block_id_ - 1); |
| +} |
| + |
| + |
| static bool IsGetMainClosure(const String& name) { |
| if (name.Length() < 16) return false; |
| const char* cstr = "_getMainClosure@"; |
| @@ -3564,13 +3666,17 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) { |
| switch (function.kind()) { |
| case RawFunction::kClosureFunction: |
| + case RawFunction::kConvertedClosureFunction: |
| case RawFunction::kRegularFunction: |
| case RawFunction::kGetterFunction: |
| case RawFunction::kSetterFunction: { |
| ReadUntilFunctionNode(); // read until function node. |
| - return function.IsImplicitClosureFunction() |
| - ? BuildGraphOfImplicitClosureFunction(function) |
| - : BuildGraphOfFunction(is_in_builtin_library_toplevel); |
| + if (function.IsImplicitClosureFunction()) { |
| + return BuildGraphOfImplicitClosureFunction(function); |
| + } else if (function.IsConvertedClosureFunction()) { |
| + return BuildGraphOfConvertedClosureFunction(function); |
| + } |
| + return BuildGraphOfFunction(is_in_builtin_library_toplevel); |
| } |
| case RawFunction::kConstructor: { |
| bool is_factory = function.IsFactory(); |
| @@ -3701,6 +3807,16 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { |
| return BuildBoolLiteral(false, position); |
| case kNullLiteral: |
| return BuildNullLiteral(position); |
| + case kVectorCreation: |
| + return BuildVectorCreation(position); |
| + case kVectorGet: |
| + return BuildVectorGet(position); |
| + case kVectorSet: |
| + return BuildVectorSet(position); |
| + case kVectorCopy: |
| + return BuildVectorCopy(position); |
| + case kClosureCreation: |
| + return BuildClosureCreation(position); |
| default: |
| UNREACHABLE(); |
| } |
| @@ -3856,6 +3972,7 @@ void StreamingFlowGraphBuilder::SkipDartType() { |
| case kDynamicType: |
| case kVoidType: |
| case kBottomType: |
| + case kVectorType: |
| // those contain nothing. |
| return; |
| case kInterfaceType: |
| @@ -3900,8 +4017,8 @@ void StreamingFlowGraphBuilder::SkipInterfaceType(bool simple) { |
| void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) { |
| if (!simple) { |
| SkipTypeParametersList(); // read type_parameters. |
| - ReadUInt(); // read required parameter count. |
| - ReadUInt(); // read total parameter count. |
| + ReadUInt(); // read required parameter count. |
| + ReadUInt(); // read total parameter count. |
| } |
| SkipListOfDartTypes(); // read positional_parameters types. |
| @@ -4050,8 +4167,8 @@ void StreamingFlowGraphBuilder::SkipExpression() { |
| SkipOptionalDartType(); // read unused static type. |
| return; |
| case kStringConcatenation: |
| - ReadPosition(); // read position. |
| - SkipListOfExpressions(); // read list of expressions. |
| + ReadPosition(); // read position. |
| + SkipListOfExpressions(); // read list of expressions. |
| return; |
| case kIsExpression: |
| ReadPosition(); // read position. |
| @@ -4080,9 +4197,9 @@ void StreamingFlowGraphBuilder::SkipExpression() { |
| return; |
| case kListLiteral: |
| case kConstListLiteral: |
| - ReadPosition(); // read position. |
| - SkipDartType(); // read type. |
| - SkipListOfExpressions(); // read list of expressions. |
| + ReadPosition(); // read position. |
| + SkipDartType(); // read type. |
| + SkipListOfExpressions(); // read list of expressions. |
| return; |
| case kMapLiteral: |
| case kConstMapLiteral: { |
| @@ -4103,6 +4220,26 @@ void StreamingFlowGraphBuilder::SkipExpression() { |
| SkipVariableDeclaration(); // read variable declaration. |
| SkipExpression(); // read expression. |
| return; |
| + case kVectorCreation: |
| + ReadUInt(); // read value. |
| + return; |
| + case kVectorGet: |
| + SkipExpression(); // read vector expression. |
| + ReadUInt(); // read index. |
| + return; |
| + case kVectorSet: |
| + SkipExpression(); // read vector expression. |
| + ReadUInt(); // read index. |
| + SkipExpression(); // read value. |
| + return; |
| + case kVectorCopy: |
| + SkipExpression(); // read vector expression. |
| + return; |
| + case kClosureCreation: |
| + SkipCanonicalNameReference(); // read top-level function reference. |
| + SkipExpression(); // read context vector. |
| + SkipDartType(); // read function type. |
| + return; |
| case kBigIntLiteral: |
| SkipStringReference(); // read string reference. |
| return; |
| @@ -4175,12 +4312,12 @@ void StreamingFlowGraphBuilder::SkipStatement() { |
| return; |
| case kForStatement: { |
| SkipListOfVariableDeclarations(); // read variables. |
| - Tag tag = ReadTag(); // Read first part of condition. |
| + Tag tag = ReadTag(); // Read first part of condition. |
| if (tag == kSomething) { |
| SkipExpression(); // read rest of condition. |
| } |
| SkipListOfExpressions(); // read updates. |
| - SkipStatement(); // read body. |
| + SkipStatement(); // read body. |
| return; |
| } |
| case kForInStatement: |
| @@ -4423,6 +4560,10 @@ Value* StreamingFlowGraphBuilder::stack() { |
| return flow_graph_builder_->stack_; |
| } |
| +void StreamingFlowGraphBuilder::Push(Definition* definition) { |
| + flow_graph_builder_->Push(definition); |
| +} |
| + |
| Value* StreamingFlowGraphBuilder::Pop() { |
| return flow_graph_builder_->Pop(); |
| } |
| @@ -4459,12 +4600,12 @@ intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() { |
| intptr_t StreamingFlowGraphBuilder::PeekArgumentsTypeCount() { |
| AlternativeReadingScope alt(reader_); |
| - ReadUInt(); // read arguments count. |
| - return ReadListLength(); // read length of types list. |
| + ReadUInt(); // read arguments count. |
| + return ReadListLength(); // read length of types list. |
| } |
| void StreamingFlowGraphBuilder::SkipArgumentsBeforeActualArguments() { |
| - ReadUInt(); // read arguments count. |
| + ReadUInt(); // read arguments count. |
| SkipListOfDartTypes(); // read list of types. |
| } |
| @@ -4589,6 +4730,20 @@ Fragment StreamingFlowGraphBuilder::AllocateObject(const dart::Class& klass, |
| return flow_graph_builder_->AllocateObject(klass, argument_count); |
| } |
| +Fragment StreamingFlowGraphBuilder::AllocateObject( |
| + const dart::Class& klass, |
| + const Function& closure_function) { |
| + return flow_graph_builder_->AllocateObject(klass, closure_function); |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::AllocateContext(int size) { |
| + return flow_graph_builder_->AllocateContext(size); |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::LoadField(intptr_t offset) { |
| + return flow_graph_builder_->LoadField(offset); |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::InstanceCall(TokenPosition position, |
| const dart::String& name, |
| Token::Kind kind, |
| @@ -4609,6 +4764,11 @@ Fragment StreamingFlowGraphBuilder::StoreStaticField(TokenPosition position, |
| return flow_graph_builder_->StoreStaticField(position, field); |
| } |
| +Fragment StreamingFlowGraphBuilder::StoreInstanceField(TokenPosition position, |
| + intptr_t offset) { |
| + return flow_graph_builder_->StoreInstanceField(position, offset); |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::StringInterpolate(TokenPosition position) { |
| return flow_graph_builder_->StringInterpolate(position); |
| } |
| @@ -5519,9 +5679,10 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) { |
| if (dart::FlowGraphBuilder::SimpleInstanceOfType(type)) { |
| instructions += Constant(type); |
| instructions += PushArgument(); // Type. |
| - instructions += InstanceCall(position, dart::Library::PrivateCoreLibName( |
| - Symbols::_simpleInstanceOf()), |
| - Token::kIS, 2, 2); // 2 checked arguments. |
| + instructions += InstanceCall( |
| + position, |
| + dart::Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), |
| + Token::kIS, 2, 2); // 2 checked arguments. |
| return instructions; |
| } |
| @@ -5789,8 +5950,8 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() { |
| Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) { |
| if (position != NULL) *position = TokenPosition::kNoSource; |
| - Fragment instructions = BuildVariableDeclaration(); // read variable. |
| - instructions += BuildExpression(); // read body. |
| + Fragment instructions = BuildVariableDeclaration(); // read variable. |
| + instructions += BuildExpression(); // read body. |
| return instructions; |
| } |
| @@ -5851,6 +6012,93 @@ Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) { |
| return Constant(Instance::ZoneHandle(Z, Instance::null())); |
| } |
| +Fragment StreamingFlowGraphBuilder::BuildVectorCreation( |
| + TokenPosition* position) { |
| + if (position != NULL) *position = TokenPosition::kNoSource; |
| + |
| + intptr_t size = ReadUInt(); // read size. |
| + return AllocateContext(size); |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::BuildVectorGet(TokenPosition* position) { |
| + if (position != NULL) *position = TokenPosition::kNoSource; |
| + |
| + Fragment instructions = BuildExpression(); // read expression. |
| + intptr_t index = ReadUInt(); // read index. |
| + instructions += LoadField(Context::variable_offset(index)); |
| + return instructions; |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::BuildVectorSet(TokenPosition* position) { |
| + if (position != NULL) *position = TokenPosition::kNoSource; |
| + |
| + Fragment instructions = BuildExpression(); // read vector expression. |
| + intptr_t index = ReadUInt(); // read index. |
| + instructions += BuildExpression(); // read value expression. |
| + |
| + // The assigned value is the result of the expression. |
| + LocalVariable* result = MakeTemporary(); |
| + |
| + Value* value = Pop(); |
| + StoreInstanceFieldInstr* store = new (Z) |
| + StoreInstanceFieldInstr(Context::variable_offset(index), Pop(), value, |
| + kNoStoreBarrier, TokenPosition::kNoSource); |
| + instructions <<= store; |
| + |
| + // Load the result that is stored in the temporary variable. |
| + instructions += LoadLocal(result); |
| + |
| + return instructions; |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::BuildVectorCopy(TokenPosition* position) { |
| + if (position != NULL) *position = TokenPosition::kNoSource; |
| + |
| + Fragment instructions = BuildExpression(); // read vector expression. |
| + CloneContextInstr* clone_instruction = new (Z) CloneContextInstr( |
| + TokenPosition::kNoSource, Pop(), Thread::Current()->GetNextDeoptId()); |
| + instructions <<= clone_instruction; |
| + Push(clone_instruction); |
| + |
| + return instructions; |
| +} |
| + |
| +Fragment StreamingFlowGraphBuilder::BuildClosureCreation( |
| + TokenPosition* position) { |
| + if (position != NULL) *position = TokenPosition::kNoSource; |
| + |
| + NameIndex function_reference = |
| + ReadCanonicalNameReference(); // read function reference. |
| + Function& function = Function::ZoneHandle( |
| + Z, H.LookupStaticMethodByKernelProcedure(function_reference)); |
| + function = function.ConvertedClosureFunction(); |
| + ASSERT(!function.IsNull()); |
| + |
| + const dart::Class& closure_class = |
| + dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); |
| + Fragment instructions = AllocateObject(closure_class, function); |
| + LocalVariable* closure = MakeTemporary(); |
| + |
| + instructions += BuildExpression(); // read context vector. |
| + LocalVariable* context = MakeTemporary(); |
| + |
| + instructions += LoadLocal(closure); |
| + instructions += Constant(function); |
| + instructions += |
| + StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset()); |
| + |
| + instructions += LoadLocal(closure); |
| + instructions += LoadLocal(context); |
| + instructions += |
| + StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset()); |
| + |
| + instructions += Drop(); |
| + |
| + SkipDartType(); // skip function type of the closure. |
| + |
| + return instructions; |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::BuildInvalidStatement() { |
| H.ReportError("Invalid statements not implemented yet!"); |
| return Fragment(); |