| OLD | NEW | 
|    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file |    1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|    2 // for details. All rights reserved. Use of this source code is governed by a |    2 // for details. All rights reserved. Use of this source code is governed by a | 
|    3 // BSD-style license that can be found in the LICENSE file. |    3 // BSD-style license that can be found in the LICENSE file. | 
|    4 // Class for intrinsifying functions. |    4 // Class for intrinsifying functions. | 
|    5  |    5  | 
|    6 #include "vm/assembler.h" |    6 #include "vm/assembler.h" | 
|    7 #include "vm/intrinsifier.h" |    7 #include "vm/intrinsifier.h" | 
|    8 #include "vm/flags.h" |    8 #include "vm/flags.h" | 
|    9 #include "vm/object.h" |    9 #include "vm/object.h" | 
|   10 #include "vm/symbols.h" |   10 #include "vm/symbols.h" | 
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  126 } |  126 } | 
|  127  |  127  | 
|  128  |  128  | 
|  129 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, |  129 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, | 
|  130                                    FlowGraphCompiler* compiler) { |  130                                    FlowGraphCompiler* compiler) { | 
|  131   ZoneGrowableArray<const ICData*>* ic_data_array = |  131   ZoneGrowableArray<const ICData*>* ic_data_array = | 
|  132       new ZoneGrowableArray<const ICData*>(); |  132       new ZoneGrowableArray<const ICData*>(); | 
|  133   FlowGraphBuilder builder(parsed_function, |  133   FlowGraphBuilder builder(parsed_function, | 
|  134                            *ic_data_array, |  134                            *ic_data_array, | 
|  135                            NULL,  // NULL = not inlining. |  135                            NULL,  // NULL = not inlining. | 
|  136                            Isolate::kNoDeoptId);  // No OSR id. |  136                            Thread::kNoDeoptId);  // No OSR id. | 
|  137  |  137  | 
|  138   intptr_t block_id = builder.AllocateBlockId(); |  138   intptr_t block_id = builder.AllocateBlockId(); | 
|  139   TargetEntryInstr* normal_entry = |  139   TargetEntryInstr* normal_entry = | 
|  140       new TargetEntryInstr(block_id, |  140       new TargetEntryInstr(block_id, | 
|  141                            CatchClauseNode::kInvalidTryIndex); |  141                            CatchClauseNode::kInvalidTryIndex); | 
|  142   GraphEntryInstr* graph_entry = new GraphEntryInstr( |  142   GraphEntryInstr* graph_entry = new GraphEntryInstr( | 
|  143       parsed_function, normal_entry, Isolate::kNoDeoptId);  // No OSR id. |  143       parsed_function, normal_entry, Thread::kNoDeoptId);  // No OSR id. | 
|  144   FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); |  144   FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); | 
|  145   const Function& function = parsed_function.function(); |  145   const Function& function = parsed_function.function(); | 
|  146   switch (function.recognized_kind()) { |  146   switch (function.recognized_kind()) { | 
|  147 #define EMIT_CASE(class_name, function_name, enum_name, fp)                    \ |  147 #define EMIT_CASE(class_name, function_name, enum_name, fp)                    \ | 
|  148     case MethodRecognizer::k##enum_name:                                       \ |  148     case MethodRecognizer::k##enum_name:                                       \ | 
|  149       if (!Build_##enum_name(graph)) return false;                             \ |  149       if (!Build_##enum_name(graph)) return false;                             \ | 
|  150       break; |  150       break; | 
|  151  |  151  | 
|  152     GRAPH_INTRINSICS_LIST(EMIT_CASE); |  152     GRAPH_INTRINSICS_LIST(EMIT_CASE); | 
|  153     default: |  153     default: | 
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  267     return flow_graph_->function().token_pos(); |  267     return flow_graph_->function().token_pos(); | 
|  268   } |  268   } | 
|  269  |  269  | 
|  270   Definition* AddNullDefinition() { |  270   Definition* AddNullDefinition() { | 
|  271     return AddDefinition( |  271     return AddDefinition( | 
|  272         new ConstantInstr(Object::ZoneHandle(Object::null()))); |  272         new ConstantInstr(Object::ZoneHandle(Object::null()))); | 
|  273   } |  273   } | 
|  274  |  274  | 
|  275   Definition* AddUnboxInstr(Representation rep, Value* value) { |  275   Definition* AddUnboxInstr(Representation rep, Value* value) { | 
|  276     Definition* unboxed_value = AddDefinition( |  276     Definition* unboxed_value = AddDefinition( | 
|  277         UnboxInstr::Create(rep, value, Isolate::kNoDeoptId)); |  277         UnboxInstr::Create(rep, value, Thread::kNoDeoptId)); | 
|  278     // Manually adjust reaching type because there is no type propagation |  278     // Manually adjust reaching type because there is no type propagation | 
|  279     // when building intrinsics. |  279     // when building intrinsics. | 
|  280     unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( |  280     unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( | 
|  281         CompileType::FromCid(CidForRepresentation(rep)))); |  281         CompileType::FromCid(CidForRepresentation(rep)))); | 
|  282     return unboxed_value; |  282     return unboxed_value; | 
|  283   } |  283   } | 
|  284  |  284  | 
|  285  private: |  285  private: | 
|  286   FlowGraph* flow_graph_; |  286   FlowGraph* flow_graph_; | 
|  287   BlockEntryInstr* entry_; |  287   BlockEntryInstr* entry_; | 
|  288   Instruction* current_; |  288   Instruction* current_; | 
|  289 }; |  289 }; | 
|  290  |  290  | 
|  291  |  291  | 
|  292 static void PrepareIndexedOp(BlockBuilder* builder, |  292 static void PrepareIndexedOp(BlockBuilder* builder, | 
|  293                              Definition* array, |  293                              Definition* array, | 
|  294                              Definition* index, |  294                              Definition* index, | 
|  295                              intptr_t length_offset) { |  295                              intptr_t length_offset) { | 
|  296   intptr_t token_pos = builder->TokenPos(); |  296   intptr_t token_pos = builder->TokenPos(); | 
|  297   builder->AddInstruction( |  297   builder->AddInstruction( | 
|  298       new CheckSmiInstr(new Value(index), |  298       new CheckSmiInstr(new Value(index), | 
|  299                         Isolate::kNoDeoptId, |  299                         Thread::kNoDeoptId, | 
|  300                         token_pos)); |  300                         token_pos)); | 
|  301  |  301  | 
|  302   Definition* length = builder->AddDefinition( |  302   Definition* length = builder->AddDefinition( | 
|  303       new LoadFieldInstr(new Value(array), |  303       new LoadFieldInstr(new Value(array), | 
|  304                          length_offset, |  304                          length_offset, | 
|  305                          Type::ZoneHandle(Type::SmiType()), |  305                          Type::ZoneHandle(Type::SmiType()), | 
|  306                          Scanner::kNoSourcePos)); |  306                          Scanner::kNoSourcePos)); | 
|  307   builder->AddInstruction( |  307   builder->AddInstruction( | 
|  308       new CheckArrayBoundInstr(new Value(length), |  308       new CheckArrayBoundInstr(new Value(length), | 
|  309                                new Value(index), |  309                                new Value(index), | 
|  310                                Isolate::kNoDeoptId)); |  310                                Thread::kNoDeoptId)); | 
|  311 } |  311 } | 
|  312  |  312  | 
|  313  |  313  | 
|  314 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { |  314 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { | 
|  315   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  315   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  316   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  316   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  317   BlockBuilder builder(flow_graph, normal_entry); |  317   BlockBuilder builder(flow_graph, normal_entry); | 
|  318  |  318  | 
|  319   Definition* index = builder.AddParameter(1); |  319   Definition* index = builder.AddParameter(1); | 
|  320   Definition* array = builder.AddParameter(2); |  320   Definition* array = builder.AddParameter(2); | 
|  321  |  321  | 
|  322   PrepareIndexedOp(&builder, array, index, Array::length_offset()); |  322   PrepareIndexedOp(&builder, array, index, Array::length_offset()); | 
|  323  |  323  | 
|  324   Definition* result = builder.AddDefinition( |  324   Definition* result = builder.AddDefinition( | 
|  325       new LoadIndexedInstr(new Value(array), |  325       new LoadIndexedInstr(new Value(array), | 
|  326                            new Value(index), |  326                            new Value(index), | 
|  327                            Instance::ElementSizeFor(kArrayCid),  // index scale |  327                            Instance::ElementSizeFor(kArrayCid),  // index scale | 
|  328                            kArrayCid, |  328                            kArrayCid, | 
|  329                            Isolate::kNoDeoptId, |  329                            Thread::kNoDeoptId, | 
|  330                            builder.TokenPos())); |  330                            builder.TokenPos())); | 
|  331   builder.AddIntrinsicReturn(new Value(result)); |  331   builder.AddIntrinsicReturn(new Value(result)); | 
|  332   return true; |  332   return true; | 
|  333 } |  333 } | 
|  334  |  334  | 
|  335  |  335  | 
|  336 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { |  336 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { | 
|  337   return Build_ObjectArrayGetIndexed(flow_graph); |  337   return Build_ObjectArrayGetIndexed(flow_graph); | 
|  338 } |  338 } | 
|  339  |  339  | 
|  340  |  340  | 
|  341 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { |  341 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { | 
|  342   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  342   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  343   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  343   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  344   BlockBuilder builder(flow_graph, normal_entry); |  344   BlockBuilder builder(flow_graph, normal_entry); | 
|  345  |  345  | 
|  346   Definition* index = builder.AddParameter(1); |  346   Definition* index = builder.AddParameter(1); | 
|  347   Definition* array = builder.AddParameter(2); |  347   Definition* array = builder.AddParameter(2); | 
|  348  |  348  | 
|  349   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  349   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  350  |  350  | 
|  351   Definition* result = builder.AddDefinition( |  351   Definition* result = builder.AddDefinition( | 
|  352       new LoadIndexedInstr(new Value(array), |  352       new LoadIndexedInstr(new Value(array), | 
|  353                            new Value(index), |  353                            new Value(index), | 
|  354                            1,  // index scale |  354                            1,  // index scale | 
|  355                            kTypedDataUint8ArrayCid, |  355                            kTypedDataUint8ArrayCid, | 
|  356                            Isolate::kNoDeoptId, |  356                            Thread::kNoDeoptId, | 
|  357                            builder.TokenPos())); |  357                            builder.TokenPos())); | 
|  358   builder.AddIntrinsicReturn(new Value(result)); |  358   builder.AddIntrinsicReturn(new Value(result)); | 
|  359   return true; |  359   return true; | 
|  360 } |  360 } | 
|  361  |  361  | 
|  362  |  362  | 
|  363 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { |  363 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { | 
|  364   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  364   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  365   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  365   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  366   BlockBuilder builder(flow_graph, normal_entry); |  366   BlockBuilder builder(flow_graph, normal_entry); | 
|  367  |  367  | 
|  368   Definition* index = builder.AddParameter(1); |  368   Definition* index = builder.AddParameter(1); | 
|  369   Definition* array = builder.AddParameter(2); |  369   Definition* array = builder.AddParameter(2); | 
|  370  |  370  | 
|  371   PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); |  371   PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | 
|  372  |  372  | 
|  373   Definition* elements = builder.AddDefinition( |  373   Definition* elements = builder.AddDefinition( | 
|  374       new LoadUntaggedInstr(new Value(array), |  374       new LoadUntaggedInstr(new Value(array), | 
|  375                             ExternalTypedData::data_offset())); |  375                             ExternalTypedData::data_offset())); | 
|  376   Definition* result = builder.AddDefinition( |  376   Definition* result = builder.AddDefinition( | 
|  377       new LoadIndexedInstr(new Value(elements), |  377       new LoadIndexedInstr(new Value(elements), | 
|  378                            new Value(index), |  378                            new Value(index), | 
|  379                            1,  // index scale |  379                            1,  // index scale | 
|  380                            kExternalTypedDataUint8ArrayCid, |  380                            kExternalTypedDataUint8ArrayCid, | 
|  381                            Isolate::kNoDeoptId, |  381                            Thread::kNoDeoptId, | 
|  382                            builder.TokenPos())); |  382                            builder.TokenPos())); | 
|  383   builder.AddIntrinsicReturn(new Value(result)); |  383   builder.AddIntrinsicReturn(new Value(result)); | 
|  384   return true; |  384   return true; | 
|  385 } |  385 } | 
|  386  |  386  | 
|  387  |  387  | 
|  388 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { |  388 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { | 
|  389   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  389   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  390   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  390   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  391   BlockBuilder builder(flow_graph, normal_entry); |  391   BlockBuilder builder(flow_graph, normal_entry); | 
|  392  |  392  | 
|  393   Definition* value = builder.AddParameter(1); |  393   Definition* value = builder.AddParameter(1); | 
|  394   Definition* index = builder.AddParameter(2); |  394   Definition* index = builder.AddParameter(2); | 
|  395   Definition* array = builder.AddParameter(3); |  395   Definition* array = builder.AddParameter(3); | 
|  396  |  396  | 
|  397   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  397   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  398  |  398  | 
|  399   builder.AddInstruction( |  399   builder.AddInstruction( | 
|  400       new CheckSmiInstr(new Value(value), |  400       new CheckSmiInstr(new Value(value), | 
|  401                         Isolate::kNoDeoptId, |  401                         Thread::kNoDeoptId, | 
|  402                         builder.TokenPos())); |  402                         builder.TokenPos())); | 
|  403  |  403  | 
|  404   builder.AddInstruction( |  404   builder.AddInstruction( | 
|  405       new StoreIndexedInstr(new Value(array), |  405       new StoreIndexedInstr(new Value(array), | 
|  406                             new Value(index), |  406                             new Value(index), | 
|  407                             new Value(value), |  407                             new Value(value), | 
|  408                             kNoStoreBarrier, |  408                             kNoStoreBarrier, | 
|  409                             1,  // index scale |  409                             1,  // index scale | 
|  410                             kTypedDataUint8ArrayCid, |  410                             kTypedDataUint8ArrayCid, | 
|  411                             Isolate::kNoDeoptId, |  411                             Thread::kNoDeoptId, | 
|  412                             builder.TokenPos())); |  412                             builder.TokenPos())); | 
|  413   // Return null. |  413   // Return null. | 
|  414   Definition* null_def = builder.AddNullDefinition(); |  414   Definition* null_def = builder.AddNullDefinition(); | 
|  415   builder.AddIntrinsicReturn(new Value(null_def)); |  415   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  416   return true; |  416   return true; | 
|  417 } |  417 } | 
|  418  |  418  | 
|  419  |  419  | 
|  420 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { |  420 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { | 
|  421   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  421   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  422   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  422   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  423   BlockBuilder builder(flow_graph, normal_entry); |  423   BlockBuilder builder(flow_graph, normal_entry); | 
|  424  |  424  | 
|  425   Definition* value = builder.AddParameter(1); |  425   Definition* value = builder.AddParameter(1); | 
|  426   Definition* index = builder.AddParameter(2); |  426   Definition* index = builder.AddParameter(2); | 
|  427   Definition* array = builder.AddParameter(3); |  427   Definition* array = builder.AddParameter(3); | 
|  428  |  428  | 
|  429   PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); |  429   PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | 
|  430  |  430  | 
|  431   builder.AddInstruction( |  431   builder.AddInstruction( | 
|  432       new CheckSmiInstr(new Value(value), |  432       new CheckSmiInstr(new Value(value), | 
|  433                         Isolate::kNoDeoptId, |  433                         Thread::kNoDeoptId, | 
|  434                         builder.TokenPos())); |  434                         builder.TokenPos())); | 
|  435   Definition* elements = builder.AddDefinition( |  435   Definition* elements = builder.AddDefinition( | 
|  436       new LoadUntaggedInstr(new Value(array), |  436       new LoadUntaggedInstr(new Value(array), | 
|  437                             ExternalTypedData::data_offset())); |  437                             ExternalTypedData::data_offset())); | 
|  438   builder.AddInstruction( |  438   builder.AddInstruction( | 
|  439       new StoreIndexedInstr(new Value(elements), |  439       new StoreIndexedInstr(new Value(elements), | 
|  440                             new Value(index), |  440                             new Value(index), | 
|  441                             new Value(value), |  441                             new Value(value), | 
|  442                             kNoStoreBarrier, |  442                             kNoStoreBarrier, | 
|  443                             1,  // index scale |  443                             1,  // index scale | 
|  444                             kExternalTypedDataUint8ArrayCid, |  444                             kExternalTypedDataUint8ArrayCid, | 
|  445                             Isolate::kNoDeoptId, |  445                             Thread::kNoDeoptId, | 
|  446                             builder.TokenPos())); |  446                             builder.TokenPos())); | 
|  447   // Return null. |  447   // Return null. | 
|  448   Definition* null_def = builder.AddNullDefinition(); |  448   Definition* null_def = builder.AddNullDefinition(); | 
|  449   builder.AddIntrinsicReturn(new Value(null_def)); |  449   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  450   return true; |  450   return true; | 
|  451 } |  451 } | 
|  452  |  452  | 
|  453  |  453  | 
|  454 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { |  454 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { | 
|  455   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  455   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  456   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  456   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  457   BlockBuilder builder(flow_graph, normal_entry); |  457   BlockBuilder builder(flow_graph, normal_entry); | 
|  458  |  458  | 
|  459   Definition* value = builder.AddParameter(1); |  459   Definition* value = builder.AddParameter(1); | 
|  460   Definition* index = builder.AddParameter(2); |  460   Definition* index = builder.AddParameter(2); | 
|  461   Definition* array = builder.AddParameter(3); |  461   Definition* array = builder.AddParameter(3); | 
|  462  |  462  | 
|  463   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  463   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  464  |  464  | 
|  465   Definition* unboxed_value = |  465   Definition* unboxed_value = | 
|  466       builder.AddUnboxInstr(kUnboxedUint32, new Value(value)); |  466       builder.AddUnboxInstr(kUnboxedUint32, new Value(value)); | 
|  467  |  467  | 
|  468   builder.AddInstruction( |  468   builder.AddInstruction( | 
|  469       new StoreIndexedInstr(new Value(array), |  469       new StoreIndexedInstr(new Value(array), | 
|  470                             new Value(index), |  470                             new Value(index), | 
|  471                             new Value(unboxed_value), |  471                             new Value(unboxed_value), | 
|  472                             kNoStoreBarrier, |  472                             kNoStoreBarrier, | 
|  473                             4,  // index scale |  473                             4,  // index scale | 
|  474                             kTypedDataUint32ArrayCid, |  474                             kTypedDataUint32ArrayCid, | 
|  475                             Isolate::kNoDeoptId, |  475                             Thread::kNoDeoptId, | 
|  476                             builder.TokenPos())); |  476                             builder.TokenPos())); | 
|  477   // Return null. |  477   // Return null. | 
|  478   Definition* null_def = builder.AddNullDefinition(); |  478   Definition* null_def = builder.AddNullDefinition(); | 
|  479   builder.AddIntrinsicReturn(new Value(null_def)); |  479   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  480   return true; |  480   return true; | 
|  481 } |  481 } | 
|  482  |  482  | 
|  483  |  483  | 
|  484 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { |  484 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { | 
|  485   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  485   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  486   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  486   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  487   BlockBuilder builder(flow_graph, normal_entry); |  487   BlockBuilder builder(flow_graph, normal_entry); | 
|  488  |  488  | 
|  489   Definition* index = builder.AddParameter(1); |  489   Definition* index = builder.AddParameter(1); | 
|  490   Definition* array = builder.AddParameter(2); |  490   Definition* array = builder.AddParameter(2); | 
|  491  |  491  | 
|  492   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  492   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  493  |  493  | 
|  494   Definition* unboxed_value = builder.AddDefinition( |  494   Definition* unboxed_value = builder.AddDefinition( | 
|  495       new LoadIndexedInstr(new Value(array), |  495       new LoadIndexedInstr(new Value(array), | 
|  496                            new Value(index), |  496                            new Value(index), | 
|  497                            4,  // index scale |  497                            4,  // index scale | 
|  498                            kTypedDataUint32ArrayCid, |  498                            kTypedDataUint32ArrayCid, | 
|  499                            Isolate::kNoDeoptId, |  499                            Thread::kNoDeoptId, | 
|  500                            builder.TokenPos())); |  500                            builder.TokenPos())); | 
|  501   Definition* result = builder.AddDefinition( |  501   Definition* result = builder.AddDefinition( | 
|  502       BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); |  502       BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); | 
|  503   builder.AddIntrinsicReturn(new Value(result)); |  503   builder.AddIntrinsicReturn(new Value(result)); | 
|  504   return true; |  504   return true; | 
|  505 } |  505 } | 
|  506  |  506  | 
|  507  |  507  | 
|  508 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { |  508 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { | 
|  509   if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |  509   if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 
|  510  |  510  | 
|  511   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  511   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  512   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  512   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  513   BlockBuilder builder(flow_graph, normal_entry); |  513   BlockBuilder builder(flow_graph, normal_entry); | 
|  514  |  514  | 
|  515   Definition* value = builder.AddParameter(1); |  515   Definition* value = builder.AddParameter(1); | 
|  516   Definition* index = builder.AddParameter(2); |  516   Definition* index = builder.AddParameter(2); | 
|  517   Definition* array = builder.AddParameter(3); |  517   Definition* array = builder.AddParameter(3); | 
|  518  |  518  | 
|  519   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  519   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  520  |  520  | 
|  521   const ICData& value_check = ICData::ZoneHandle(ICData::New( |  521   const ICData& value_check = ICData::ZoneHandle(ICData::New( | 
|  522       flow_graph->function(), |  522       flow_graph->function(), | 
|  523       String::Handle(flow_graph->function().name()), |  523       String::Handle(flow_graph->function().name()), | 
|  524       Object::empty_array(),  // Dummy args. descr. |  524       Object::empty_array(),  // Dummy args. descr. | 
|  525       Isolate::kNoDeoptId, |  525       Thread::kNoDeoptId, | 
|  526       1)); |  526       1)); | 
|  527   value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); |  527   value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); | 
|  528   builder.AddInstruction( |  528   builder.AddInstruction( | 
|  529       new CheckClassInstr(new Value(value), |  529       new CheckClassInstr(new Value(value), | 
|  530                           Isolate::kNoDeoptId, |  530                           Thread::kNoDeoptId, | 
|  531                           value_check, |  531                           value_check, | 
|  532                           builder.TokenPos())); |  532                           builder.TokenPos())); | 
|  533   Definition* double_value = |  533   Definition* double_value = | 
|  534       builder.AddUnboxInstr(kUnboxedDouble, new Value(value)); |  534       builder.AddUnboxInstr(kUnboxedDouble, new Value(value)); | 
|  535  |  535  | 
|  536   builder.AddInstruction( |  536   builder.AddInstruction( | 
|  537       new StoreIndexedInstr(new Value(array), |  537       new StoreIndexedInstr(new Value(array), | 
|  538                             new Value(index), |  538                             new Value(index), | 
|  539                             new Value(double_value), |  539                             new Value(double_value), | 
|  540                             kNoStoreBarrier, |  540                             kNoStoreBarrier, | 
|  541                             8,  // index scale |  541                             8,  // index scale | 
|  542                             kTypedDataFloat64ArrayCid, |  542                             kTypedDataFloat64ArrayCid, | 
|  543                             Isolate::kNoDeoptId, |  543                             Thread::kNoDeoptId, | 
|  544                             builder.TokenPos())); |  544                             builder.TokenPos())); | 
|  545   // Return null. |  545   // Return null. | 
|  546   Definition* null_def = builder.AddNullDefinition(); |  546   Definition* null_def = builder.AddNullDefinition(); | 
|  547   builder.AddIntrinsicReturn(new Value(null_def)); |  547   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  548   return true; |  548   return true; | 
|  549 } |  549 } | 
|  550  |  550  | 
|  551  |  551  | 
|  552 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { |  552 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { | 
|  553   if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |  553   if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 
|  554  |  554  | 
|  555   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  555   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  556   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  556   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  557   BlockBuilder builder(flow_graph, normal_entry); |  557   BlockBuilder builder(flow_graph, normal_entry); | 
|  558  |  558  | 
|  559   Definition* index = builder.AddParameter(1); |  559   Definition* index = builder.AddParameter(1); | 
|  560   Definition* array = builder.AddParameter(2); |  560   Definition* array = builder.AddParameter(2); | 
|  561  |  561  | 
|  562   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |  562   PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 
|  563  |  563  | 
|  564   Definition* unboxed_value = builder.AddDefinition( |  564   Definition* unboxed_value = builder.AddDefinition( | 
|  565       new LoadIndexedInstr(new Value(array), |  565       new LoadIndexedInstr(new Value(array), | 
|  566                            new Value(index), |  566                            new Value(index), | 
|  567                            8,  // index scale |  567                            8,  // index scale | 
|  568                            kTypedDataFloat64ArrayCid, |  568                            kTypedDataFloat64ArrayCid, | 
|  569                            Isolate::kNoDeoptId, |  569                            Thread::kNoDeoptId, | 
|  570                            builder.TokenPos())); |  570                            builder.TokenPos())); | 
|  571   Definition* result = builder.AddDefinition( |  571   Definition* result = builder.AddDefinition( | 
|  572       BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); |  572       BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); | 
|  573   builder.AddIntrinsicReturn(new Value(result)); |  573   builder.AddIntrinsicReturn(new Value(result)); | 
|  574   return true; |  574   return true; | 
|  575 } |  575 } | 
|  576  |  576  | 
|  577  |  577  | 
|  578 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { |  578 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { | 
|  579   if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |  579   if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; | 
|  580  |  580  | 
|  581   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  581   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  582   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  582   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  583   BlockBuilder builder(flow_graph, normal_entry); |  583   BlockBuilder builder(flow_graph, normal_entry); | 
|  584  |  584  | 
|  585   Definition* right = builder.AddParameter(1); |  585   Definition* right = builder.AddParameter(1); | 
|  586   Definition* left = builder.AddParameter(2); |  586   Definition* left = builder.AddParameter(2); | 
|  587  |  587  | 
|  588   const ICData& value_check = ICData::ZoneHandle(ICData::New( |  588   const ICData& value_check = ICData::ZoneHandle(ICData::New( | 
|  589       flow_graph->function(), |  589       flow_graph->function(), | 
|  590       String::Handle(flow_graph->function().name()), |  590       String::Handle(flow_graph->function().name()), | 
|  591       Object::empty_array(),  // Dummy args. descr. |  591       Object::empty_array(),  // Dummy args. descr. | 
|  592       Isolate::kNoDeoptId, |  592       Thread::kNoDeoptId, | 
|  593       1)); |  593       1)); | 
|  594   value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); |  594   value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); | 
|  595   // Check argument. Receiver (left) is known to be a Float32x4. |  595   // Check argument. Receiver (left) is known to be a Float32x4. | 
|  596   builder.AddInstruction( |  596   builder.AddInstruction( | 
|  597       new CheckClassInstr(new Value(right), |  597       new CheckClassInstr(new Value(right), | 
|  598                           Isolate::kNoDeoptId, |  598                           Thread::kNoDeoptId, | 
|  599                           value_check, |  599                           value_check, | 
|  600                           builder.TokenPos())); |  600                           builder.TokenPos())); | 
|  601   Definition* left_simd = |  601   Definition* left_simd = | 
|  602       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left)); |  602       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left)); | 
|  603  |  603  | 
|  604   Definition* right_simd = |  604   Definition* right_simd = | 
|  605       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right)); |  605       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right)); | 
|  606  |  606  | 
|  607   Definition* unboxed_result = builder.AddDefinition( |  607   Definition* unboxed_result = builder.AddDefinition( | 
|  608       new BinaryFloat32x4OpInstr(kind, |  608       new BinaryFloat32x4OpInstr(kind, | 
|  609                                  new Value(left_simd), |  609                                  new Value(left_simd), | 
|  610                                  new Value(right_simd), |  610                                  new Value(right_simd), | 
|  611                                  Isolate::kNoDeoptId)); |  611                                  Thread::kNoDeoptId)); | 
|  612   Definition* result = builder.AddDefinition( |  612   Definition* result = builder.AddDefinition( | 
|  613       BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); |  613       BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); | 
|  614   builder.AddIntrinsicReturn(new Value(result)); |  614   builder.AddIntrinsicReturn(new Value(result)); | 
|  615   return true; |  615   return true; | 
|  616 } |  616 } | 
|  617  |  617  | 
|  618  |  618  | 
|  619 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { |  619 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { | 
|  620   return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); |  620   return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); | 
|  621 } |  621 } | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|  640  |  640  | 
|  641   Definition* receiver = builder.AddParameter(1); |  641   Definition* receiver = builder.AddParameter(1); | 
|  642  |  642  | 
|  643   Definition* unboxed_receiver = |  643   Definition* unboxed_receiver = | 
|  644       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver)); |  644       builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver)); | 
|  645  |  645  | 
|  646   Definition* unboxed_result = builder.AddDefinition( |  646   Definition* unboxed_result = builder.AddDefinition( | 
|  647       new Simd32x4ShuffleInstr(kind, |  647       new Simd32x4ShuffleInstr(kind, | 
|  648                                new Value(unboxed_receiver), |  648                                new Value(unboxed_receiver), | 
|  649                                0, |  649                                0, | 
|  650                                Isolate::kNoDeoptId)); |  650                                Thread::kNoDeoptId)); | 
|  651  |  651  | 
|  652   Definition* result = builder.AddDefinition( |  652   Definition* result = builder.AddDefinition( | 
|  653       BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |  653       BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 
|  654   builder.AddIntrinsicReturn(new Value(result)); |  654   builder.AddIntrinsicReturn(new Value(result)); | 
|  655   return true; |  655   return true; | 
|  656 } |  656 } | 
|  657  |  657  | 
|  658  |  658  | 
|  659 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { |  659 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { | 
|  660   return BuildFloat32x4Shuffle(flow_graph, |  660   return BuildFloat32x4Shuffle(flow_graph, | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  758   Definition* backing_store = builder.AddDefinition( |  758   Definition* backing_store = builder.AddDefinition( | 
|  759       new LoadFieldInstr(new Value(growable_array), |  759       new LoadFieldInstr(new Value(growable_array), | 
|  760                          GrowableObjectArray::data_offset(), |  760                          GrowableObjectArray::data_offset(), | 
|  761                          Type::ZoneHandle(), |  761                          Type::ZoneHandle(), | 
|  762                          builder.TokenPos())); |  762                          builder.TokenPos())); | 
|  763   Definition* result = builder.AddDefinition( |  763   Definition* result = builder.AddDefinition( | 
|  764       new LoadIndexedInstr(new Value(backing_store), |  764       new LoadIndexedInstr(new Value(backing_store), | 
|  765                            new Value(index), |  765                            new Value(index), | 
|  766                            Instance::ElementSizeFor(kArrayCid),  // index scale |  766                            Instance::ElementSizeFor(kArrayCid),  // index scale | 
|  767                            kArrayCid, |  767                            kArrayCid, | 
|  768                            Isolate::kNoDeoptId, |  768                            Thread::kNoDeoptId, | 
|  769                            builder.TokenPos())); |  769                            builder.TokenPos())); | 
|  770   builder.AddIntrinsicReturn(new Value(result)); |  770   builder.AddIntrinsicReturn(new Value(result)); | 
|  771   return true; |  771   return true; | 
|  772 } |  772 } | 
|  773  |  773  | 
|  774  |  774  | 
|  775 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { |  775 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { | 
|  776   if (Isolate::Current()->flags().type_checks()) { |  776   if (Isolate::Current()->flags().type_checks()) { | 
|  777     return false; |  777     return false; | 
|  778   } |  778   } | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  794                          Type::ZoneHandle(), |  794                          Type::ZoneHandle(), | 
|  795                          builder.TokenPos())); |  795                          builder.TokenPos())); | 
|  796  |  796  | 
|  797   builder.AddInstruction( |  797   builder.AddInstruction( | 
|  798       new StoreIndexedInstr(new Value(backing_store), |  798       new StoreIndexedInstr(new Value(backing_store), | 
|  799                             new Value(index), |  799                             new Value(index), | 
|  800                             new Value(value), |  800                             new Value(value), | 
|  801                             kEmitStoreBarrier, |  801                             kEmitStoreBarrier, | 
|  802                             Instance::ElementSizeFor(kArrayCid),  // index scale |  802                             Instance::ElementSizeFor(kArrayCid),  // index scale | 
|  803                             kArrayCid, |  803                             kArrayCid, | 
|  804                             Isolate::kNoDeoptId, |  804                             Thread::kNoDeoptId, | 
|  805                             builder.TokenPos())); |  805                             builder.TokenPos())); | 
|  806   // Return null. |  806   // Return null. | 
|  807   Definition* null_def = builder.AddNullDefinition(); |  807   Definition* null_def = builder.AddNullDefinition(); | 
|  808   builder.AddIntrinsicReturn(new Value(null_def)); |  808   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  809   return true; |  809   return true; | 
|  810 } |  810 } | 
|  811  |  811  | 
|  812  |  812  | 
|  813 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { |  813 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { | 
|  814   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  814   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  815   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  815   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  816   BlockBuilder builder(flow_graph, normal_entry); |  816   BlockBuilder builder(flow_graph, normal_entry); | 
|  817  |  817  | 
|  818   Definition* data = builder.AddParameter(1); |  818   Definition* data = builder.AddParameter(1); | 
|  819   Definition* growable_array = builder.AddParameter(2); |  819   Definition* growable_array = builder.AddParameter(2); | 
|  820  |  820  | 
|  821   const ICData& value_check = ICData::ZoneHandle(ICData::New( |  821   const ICData& value_check = ICData::ZoneHandle(ICData::New( | 
|  822       flow_graph->function(), |  822       flow_graph->function(), | 
|  823       String::Handle(flow_graph->function().name()), |  823       String::Handle(flow_graph->function().name()), | 
|  824       Object::empty_array(),  // Dummy args. descr. |  824       Object::empty_array(),  // Dummy args. descr. | 
|  825       Isolate::kNoDeoptId, |  825       Thread::kNoDeoptId, | 
|  826       1)); |  826       1)); | 
|  827   value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); |  827   value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); | 
|  828   builder.AddInstruction( |  828   builder.AddInstruction( | 
|  829       new CheckClassInstr(new Value(data), |  829       new CheckClassInstr(new Value(data), | 
|  830                           Isolate::kNoDeoptId, |  830                           Thread::kNoDeoptId, | 
|  831                           value_check, |  831                           value_check, | 
|  832                           builder.TokenPos())); |  832                           builder.TokenPos())); | 
|  833  |  833  | 
|  834   builder.AddInstruction( |  834   builder.AddInstruction( | 
|  835       new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), |  835       new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), | 
|  836                                   new Value(growable_array), |  836                                   new Value(growable_array), | 
|  837                                   new Value(data), |  837                                   new Value(data), | 
|  838                                   kEmitStoreBarrier, |  838                                   kEmitStoreBarrier, | 
|  839                                   builder.TokenPos())); |  839                                   builder.TokenPos())); | 
|  840   // Return null. |  840   // Return null. | 
|  841   Definition* null_def = builder.AddNullDefinition(); |  841   Definition* null_def = builder.AddNullDefinition(); | 
|  842   builder.AddIntrinsicReturn(new Value(null_def)); |  842   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  843   return true; |  843   return true; | 
|  844 } |  844 } | 
|  845  |  845  | 
|  846  |  846  | 
|  847 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { |  847 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { | 
|  848   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |  848   GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 
|  849   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |  849   TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 
|  850   BlockBuilder builder(flow_graph, normal_entry); |  850   BlockBuilder builder(flow_graph, normal_entry); | 
|  851  |  851  | 
|  852   Definition* length = builder.AddParameter(1); |  852   Definition* length = builder.AddParameter(1); | 
|  853   Definition* growable_array = builder.AddParameter(2); |  853   Definition* growable_array = builder.AddParameter(2); | 
|  854  |  854  | 
|  855   builder.AddInstruction( |  855   builder.AddInstruction( | 
|  856       new CheckSmiInstr(new Value(length), |  856       new CheckSmiInstr(new Value(length), | 
|  857                         Isolate::kNoDeoptId, |  857                         Thread::kNoDeoptId, | 
|  858                         builder.TokenPos())); |  858                         builder.TokenPos())); | 
|  859   builder.AddInstruction( |  859   builder.AddInstruction( | 
|  860       new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), |  860       new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), | 
|  861                                   new Value(growable_array), |  861                                   new Value(growable_array), | 
|  862                                   new Value(length), |  862                                   new Value(length), | 
|  863                                   kNoStoreBarrier, |  863                                   kNoStoreBarrier, | 
|  864                                   builder.TokenPos())); |  864                                   builder.TokenPos())); | 
|  865   Definition* null_def = builder.AddNullDefinition(); |  865   Definition* null_def = builder.AddNullDefinition(); | 
|  866   builder.AddIntrinsicReturn(new Value(null_def)); |  866   builder.AddIntrinsicReturn(new Value(null_def)); | 
|  867   return true; |  867   return true; | 
|  868 } |  868 } | 
|  869  |  869  | 
|  870 }  // namespace dart |  870 }  // namespace dart | 
| OLD | NEW |