Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1682)

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

Issue 2856543002: Use off-heap data for class check instructions (Closed)
Patch Set: Feedback from Slava: rejig inheritance of CallTargets Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 #if !defined(DART_PRECOMPILED_RUNTIME) 4 #if !defined(DART_PRECOMPILED_RUNTIME)
5 #include "vm/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/aot_optimizer.h" 7 #include "vm/aot_optimizer.h"
8 #include "vm/precompiler.h" 8 #include "vm/precompiler.h"
9 #include "vm/block_scheduler.h" 9 #include "vm/block_scheduler.h"
10 #include "vm/branch_optimizer.h" 10 #include "vm/branch_optimizer.h"
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 PolymorphicInstanceCallInstr* call, 467 PolymorphicInstanceCallInstr* call,
468 const Function& caller_function, 468 const Function& caller_function,
469 intptr_t caller_inlining_id); 469 intptr_t caller_inlining_id);
470 470
471 void Inline(); 471 void Inline();
472 472
473 private: 473 private:
474 bool CheckInlinedDuplicate(const Function& target); 474 bool CheckInlinedDuplicate(const Function& target);
475 bool CheckNonInlinedDuplicate(const Function& target); 475 bool CheckNonInlinedDuplicate(const Function& target);
476 476
477 bool TryInliningPoly(const CidRangeTarget& target); 477 bool TryInliningPoly(const TargetInfo& target);
478 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target); 478 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target);
479 479
480 TargetEntryInstr* BuildDecisionGraph(); 480 TargetEntryInstr* BuildDecisionGraph();
481 481
482 Isolate* isolate() const; 482 Isolate* isolate() const;
483 Zone* zone() const; 483 Zone* zone() const;
484 intptr_t AllocateBlockId() const; 484 intptr_t AllocateBlockId() const;
485 inline bool trace_inlining() const; 485 inline bool trace_inlining() const;
486 486
487 CallSiteInliner* const owner_; 487 CallSiteInliner* const owner_;
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 1439
1440 1440
1441 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, 1441 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner,
1442 PolymorphicInstanceCallInstr* call, 1442 PolymorphicInstanceCallInstr* call,
1443 const Function& caller_function, 1443 const Function& caller_function,
1444 intptr_t caller_inlining_id) 1444 intptr_t caller_inlining_id)
1445 : owner_(owner), 1445 : owner_(owner),
1446 call_(call), 1446 call_(call),
1447 num_variants_(call->NumberOfChecks()), 1447 num_variants_(call->NumberOfChecks()),
1448 variants_(call->targets_), 1448 variants_(call->targets_),
1449 inlined_variants_(), 1449 inlined_variants_(zone()),
1450 non_inlined_variants_(new (zone()) CallTargets()), 1450 non_inlined_variants_(new (zone()) CallTargets(zone())),
1451 inlined_entries_(num_variants_), 1451 inlined_entries_(num_variants_),
1452 exit_collector_(new (Z) InlineExitCollector(owner->caller_graph(), call)), 1452 exit_collector_(new (Z) InlineExitCollector(owner->caller_graph(), call)),
1453 caller_function_(caller_function), 1453 caller_function_(caller_function),
1454 caller_inlining_id_(caller_inlining_id) {} 1454 caller_inlining_id_(caller_inlining_id) {}
1455 1455
1456 1456
1457 Isolate* PolymorphicInliner::isolate() const { 1457 Isolate* PolymorphicInliner::isolate() const {
1458 return owner_->caller_graph()->isolate(); 1458 return owner_->caller_graph()->isolate();
1459 } 1459 }
1460 1460
(...skipping 12 matching lines...) Expand all
1473 // inlined target. This sharing is represented by using three different 1473 // inlined target. This sharing is represented by using three different
1474 // types of entries in the inlined_entries_ array: 1474 // types of entries in the inlined_entries_ array:
1475 // 1475 //
1476 // * GraphEntry: the inlined body is not shared. 1476 // * GraphEntry: the inlined body is not shared.
1477 // 1477 //
1478 // * TargetEntry: the inlined body is shared and this is the first variant. 1478 // * TargetEntry: the inlined body is shared and this is the first variant.
1479 // 1479 //
1480 // * JoinEntry: the inlined body is shared and this is a subsequent variant. 1480 // * JoinEntry: the inlined body is shared and this is a subsequent variant.
1481 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) { 1481 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
1482 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { 1482 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
1483 if ((target.raw() == inlined_variants_[i].target->raw()) && 1483 if ((target.raw() == inlined_variants_.TargetAt(i)->target->raw()) &&
1484 !MethodRecognizer::PolymorphicTarget(target)) { 1484 !MethodRecognizer::PolymorphicTarget(target)) {
1485 // The call target is shared with a previous inlined variant. Share 1485 // The call target is shared with a previous inlined variant. Share
1486 // the graph. This requires a join block at the entry, and edge-split 1486 // the graph. This requires a join block at the entry, and edge-split
1487 // form requires a target for each branch. 1487 // form requires a target for each branch.
1488 // 1488 //
1489 // Represent the sharing by recording a fresh target for the first 1489 // Represent the sharing by recording a fresh target for the first
1490 // variant and the shared join for all later variants. 1490 // variant and the shared join for all later variants.
1491 if (inlined_entries_[i]->IsGraphEntry()) { 1491 if (inlined_entries_[i]->IsGraphEntry()) {
1492 // Convert the old target entry to a new join entry. 1492 // Convert the old target entry to a new join entry.
1493 TargetEntryInstr* old_target = 1493 TargetEntryInstr* old_target =
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 return true; 1525 return true;
1526 } 1526 }
1527 } 1527 }
1528 1528
1529 return false; 1529 return false;
1530 } 1530 }
1531 1531
1532 1532
1533 bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) { 1533 bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) {
1534 for (intptr_t i = 0; i < non_inlined_variants_->length(); ++i) { 1534 for (intptr_t i = 0; i < non_inlined_variants_->length(); ++i) {
1535 if (target.raw() == non_inlined_variants_->At(i).target->raw()) { 1535 if (target.raw() == non_inlined_variants_->TargetAt(i)->target->raw()) {
1536 return true; 1536 return true;
1537 } 1537 }
1538 } 1538 }
1539 1539
1540 return false; 1540 return false;
1541 } 1541 }
1542 1542
1543 1543
1544 bool PolymorphicInliner::TryInliningPoly(const CidRangeTarget& range) { 1544 bool PolymorphicInliner::TryInliningPoly(const TargetInfo& target_info) {
1545 if ((!FLAG_precompiled_mode || 1545 if ((!FLAG_precompiled_mode ||
1546 owner_->inliner_->use_speculative_inlining()) && 1546 owner_->inliner_->use_speculative_inlining()) &&
1547 range.cid_start == range.cid_end && 1547 target_info.cid_start == target_info.cid_end &&
1548 TryInlineRecognizedMethod(range.cid_start, *range.target)) { 1548 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) {
1549 owner_->inlined_ = true; 1549 owner_->inlined_ = true;
1550 return true; 1550 return true;
1551 } 1551 }
1552 1552
1553 GrowableArray<Value*> arguments(call_->ArgumentCount()); 1553 GrowableArray<Value*> arguments(call_->ArgumentCount());
1554 for (int i = 0; i < call_->ArgumentCount(); ++i) { 1554 for (int i = 0; i < call_->ArgumentCount(); ++i) {
1555 arguments.Add(call_->PushArgumentAt(i)->value()); 1555 arguments.Add(call_->PushArgumentAt(i)->value());
1556 } 1556 }
1557 InlinedCallData call_data(call_, &arguments, caller_function_, 1557 InlinedCallData call_data(call_, &arguments, caller_function_,
1558 caller_inlining_id_); 1558 caller_inlining_id_);
1559 Function& target = Function::ZoneHandle(zone(), range.target->raw()); 1559 Function& target = Function::ZoneHandle(zone(), target_info.target->raw());
1560 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), 1560 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(),
1561 &call_data)) { 1561 &call_data)) {
1562 return false; 1562 return false;
1563 } 1563 }
1564 1564
1565 FlowGraph* callee_graph = call_data.callee_graph; 1565 FlowGraph* callee_graph = call_data.callee_graph;
1566 call_data.exit_collector->PrepareGraphs(callee_graph); 1566 call_data.exit_collector->PrepareGraphs(callee_graph);
1567 inlined_entries_.Add(callee_graph->graph_entry()); 1567 inlined_entries_.Add(callee_graph->graph_entry());
1568 exit_collector_->Union(call_data.exit_collector); 1568 exit_collector_->Union(call_data.exit_collector);
1569 1569
1570 // Replace parameter stubs and constants. Replace the receiver argument 1570 // Replace parameter stubs and constants. Replace the receiver argument
1571 // with a redefinition to prevent code from the inlined body from being 1571 // with a redefinition to prevent code from the inlined body from being
1572 // hoisted above the inlined entry. 1572 // hoisted above the inlined entry.
1573 ASSERT(arguments.length() > 0); 1573 ASSERT(arguments.length() > 0);
1574 Value* actual = arguments[0]; 1574 Value* actual = arguments[0];
1575 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z)); 1575 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z));
1576 redefinition->set_ssa_temp_index( 1576 redefinition->set_ssa_temp_index(
1577 owner_->caller_graph()->alloc_ssa_temp_index()); 1577 owner_->caller_graph()->alloc_ssa_temp_index());
1578 if (range.cid_start == range.cid_end) { 1578 if (target_info.cid_start == target_info.cid_end) {
1579 redefinition->UpdateType(CompileType::FromCid(range.cid_start)); 1579 redefinition->UpdateType(CompileType::FromCid(target_info.cid_start));
1580 } 1580 }
1581 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry()); 1581 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry());
1582 Definition* stub = (*call_data.parameter_stubs)[0]; 1582 Definition* stub = (*call_data.parameter_stubs)[0];
1583 stub->ReplaceUsesWith(redefinition); 1583 stub->ReplaceUsesWith(redefinition);
1584 1584
1585 for (intptr_t i = 1; i < arguments.length(); ++i) { 1585 for (intptr_t i = 1; i < arguments.length(); ++i) {
1586 actual = arguments[i]; 1586 actual = arguments[i];
1587 if (actual != NULL) { 1587 if (actual != NULL) {
1588 stub = (*call_data.parameter_stubs)[i]; 1588 stub = (*call_data.parameter_stubs)[i];
1589 stub->ReplaceUsesWith(actual->definition()); 1589 stub->ReplaceUsesWith(actual->definition());
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 1689
1690 Definition* receiver = call_->ArgumentAt(0); 1690 Definition* receiver = call_->ArgumentAt(0);
1691 // There are at least two variants including non-inlined ones, so we have 1691 // There are at least two variants including non-inlined ones, so we have
1692 // at least one branch on the class id. 1692 // at least one branch on the class id.
1693 LoadClassIdInstr* load_cid = 1693 LoadClassIdInstr* load_cid =
1694 new (Z) LoadClassIdInstr(new (Z) Value(receiver)); 1694 new (Z) LoadClassIdInstr(new (Z) Value(receiver));
1695 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index()); 1695 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index());
1696 cursor = AppendInstruction(cursor, load_cid); 1696 cursor = AppendInstruction(cursor, load_cid);
1697 bool follow_with_deopt = false; 1697 bool follow_with_deopt = false;
1698 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { 1698 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
1699 const CidRangeTarget& variant = inlined_variants_[i]; 1699 const CidRange& variant = inlined_variants_[i];
1700 bool test_is_range = (variant.cid_start != variant.cid_end); 1700 bool test_is_range = (variant.cid_start != variant.cid_end);
1701 bool is_last_test = (i == inlined_variants_.length() - 1); 1701 bool is_last_test = (i == inlined_variants_.length() - 1);
1702 // 1. Guard the body with a class id check. We don't need any check if 1702 // 1. Guard the body with a class id check. We don't need any check if
1703 // it's the last test and global analysis has told us that the call is 1703 // it's the last test and global analysis has told us that the call is
1704 // complete. TODO(erikcorry): Enhance CheckClassIdInstr so it can take an 1704 // complete. TODO(erikcorry): Enhance CheckClassIdInstr so it can take an
1705 // arbitrary CidRangeTarget. Currently we don't go into this branch if the 1705 // arbitrary CidRangeTarget. Currently we don't go into this branch if the
1706 // last test is a range test - instead we set the follow_with_deopt flag. 1706 // last test is a range test - instead we set the follow_with_deopt flag.
1707 if (is_last_test && (!test_is_range || call_->complete()) && 1707 if (is_last_test && (!test_is_range || call_->complete()) &&
1708 non_inlined_variants_->is_empty()) { 1708 non_inlined_variants_->is_empty()) {
1709 // If it is the last variant use a check class id instruction which can 1709 // If it is the last variant use a check class id instruction which can
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) { 1919 for (intptr_t i = 0; i < call_->ArgumentCount(); ++i) {
1920 PushArgumentInstr* push = call_->PushArgumentAt(i); 1920 PushArgumentInstr* push = call_->PushArgumentAt(i);
1921 push->ReplaceUsesWith(push->value()->definition()); 1921 push->ReplaceUsesWith(push->value()->definition());
1922 push->RemoveFromGraph(); 1922 push->RemoveFromGraph();
1923 } 1923 }
1924 } 1924 }
1925 return entry; 1925 return entry;
1926 } 1926 }
1927 1927
1928 1928
1929 static void TracePolyInlining(const CidRangeTarget& crt, 1929 static void TracePolyInlining(const CallTargets& targets,
1930 intptr_t idx,
1930 intptr_t total, 1931 intptr_t total,
1931 const char* message) { 1932 const char* message) {
1932 String& name = String::Handle(crt.target->QualifiedUserVisibleName()); 1933 String& name =
1933 int percent = total == 0 ? 0 : (100 * crt.count) / total; 1934 String::Handle(targets.TargetAt(idx)->target->QualifiedUserVisibleName());
1935 int percent = total == 0 ? 0 : (100 * targets.TargetAt(idx)->count) / total;
1934 THR_Print("%s cid %" Pd "-%" Pd ": %" Pd "/%" Pd " %d%% %s\n", 1936 THR_Print("%s cid %" Pd "-%" Pd ": %" Pd "/%" Pd " %d%% %s\n",
1935 name.ToCString(), crt.cid_start, crt.cid_end, crt.count, total, 1937 name.ToCString(), targets[idx].cid_start, targets[idx].cid_end,
1936 percent, message); 1938 targets.TargetAt(idx)->count, total, percent, message);
1937 } 1939 }
1938 1940
1939 1941
1940 bool PolymorphicInliner::trace_inlining() const { 1942 bool PolymorphicInliner::trace_inlining() const {
1941 return owner_->trace_inlining(); 1943 return owner_->trace_inlining();
1942 } 1944 }
1943 1945
1944 1946
1945 void PolymorphicInliner::Inline() { 1947 void PolymorphicInliner::Inline() {
1946 ASSERT(&variants_ == &call_->targets_); 1948 ASSERT(&variants_ == &call_->targets_);
1947 1949
1948 intptr_t total = call_->total_call_count(); 1950 intptr_t total = call_->total_call_count();
1949 for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) { 1951 for (intptr_t var_idx = 0; var_idx < variants_.length(); ++var_idx) {
1952 TargetInfo* info = variants_.TargetAt(var_idx);
1950 if (variants_.length() > FLAG_max_polymorphic_checks) { 1953 if (variants_.length() > FLAG_max_polymorphic_checks) {
1951 non_inlined_variants_->Add(variants_[var_idx]); 1954 non_inlined_variants_->Add(info);
1952 continue; 1955 continue;
1953 } 1956 }
1954 1957
1958 const Function& target = *variants_.TargetAt(var_idx)->target;
1959 const intptr_t count = variants_.TargetAt(var_idx)->count;
1960
1955 // We we almost inlined all the cases then try a little harder to inline 1961 // We we almost inlined all the cases then try a little harder to inline
1956 // the last two, because it's a big win if we inline all of them (compiler 1962 // the last two, because it's a big win if we inline all of them (compiler
1957 // can see all side effects). 1963 // can see all side effects).
1958 const bool try_harder = (var_idx >= variants_.length() - 2) && 1964 const bool try_harder = (var_idx >= variants_.length() - 2) &&
1959 non_inlined_variants_->length() == 0; 1965 non_inlined_variants_->length() == 0;
1960 const Function& target = *variants_[var_idx].target;
1961 const intptr_t count = variants_[var_idx].count;
1962 1966
1963 intptr_t size = target.optimized_instruction_count(); 1967 intptr_t size = target.optimized_instruction_count();
1964 bool small = (size != 0 && size < FLAG_inlining_size_threshold); 1968 bool small = (size != 0 && size < FLAG_inlining_size_threshold);
1965 1969
1966 // If it's less than 3% of the dispatches, we won't even consider 1970 // If it's less than 3% of the dispatches, we won't even consider
1967 // checking for the class ID and branching to another already-inlined 1971 // checking for the class ID and branching to another already-inlined
1968 // version. 1972 // version.
1969 if (!try_harder && count < (total >> 5)) { 1973 if (!try_harder && count < (total >> 5)) {
1970 TRACE_INLINING( 1974 TRACE_INLINING(
1971 TracePolyInlining(variants_[var_idx], total, "way too infrequent")); 1975 TracePolyInlining(variants_, var_idx, total, "way too infrequent"));
1972 non_inlined_variants_->Add(variants_[var_idx]); 1976 non_inlined_variants_->Add(info);
1973 continue; 1977 continue;
1974 } 1978 }
1975 1979
1976 // First check if this is the same target as an earlier inlined variant. 1980 // First check if this is the same target as an earlier inlined variant.
1977 if (CheckInlinedDuplicate(target)) { 1981 if (CheckInlinedDuplicate(target)) {
1978 TRACE_INLINING(TracePolyInlining(variants_[var_idx], total, 1982 TRACE_INLINING(TracePolyInlining(variants_, var_idx, total,
1979 "duplicate already inlined")); 1983 "duplicate already inlined"));
1980 inlined_variants_.Add(variants_[var_idx]); 1984 inlined_variants_.Add(info);
1981 continue; 1985 continue;
1982 } 1986 }
1983 1987
1984 // If it's less than 12% of the dispatches and it's not already inlined, we 1988 // If it's less than 12% of the dispatches and it's not already inlined, we
1985 // don't consider inlining. For very small functions we are willing to 1989 // don't consider inlining. For very small functions we are willing to
1986 // consider inlining for 6% of the cases. 1990 // consider inlining for 6% of the cases.
1987 if (!try_harder && count < (total >> (small ? 4 : 3))) { 1991 if (!try_harder && count < (total >> (small ? 4 : 3))) {
1988 TRACE_INLINING( 1992 TRACE_INLINING(
1989 TracePolyInlining(variants_[var_idx], total, "too infrequent")); 1993 TracePolyInlining(variants_, var_idx, total, "too infrequent"));
1990 non_inlined_variants_->Add(variants_[var_idx]); 1994 non_inlined_variants_->Add(&variants_[var_idx]);
1991 continue; 1995 continue;
1992 } 1996 }
1993 1997
1994 // Also check if this is the same target as an earlier non-inlined 1998 // Also check if this is the same target as an earlier non-inlined
1995 // variant. If so and since inlining decisions are costly, do not try 1999 // variant. If so and since inlining decisions are costly, do not try
1996 // to inline this variant. 2000 // to inline this variant.
1997 if (CheckNonInlinedDuplicate(target)) { 2001 if (CheckNonInlinedDuplicate(target)) {
1998 TRACE_INLINING( 2002 TRACE_INLINING(
1999 TracePolyInlining(variants_[var_idx], total, "already not inlined")); 2003 TracePolyInlining(variants_, var_idx, total, "already not inlined"));
2000 non_inlined_variants_->Add(variants_[var_idx]); 2004 non_inlined_variants_->Add(&variants_[var_idx]);
2001 continue; 2005 continue;
2002 } 2006 }
2003 2007
2004 // Make an inlining decision. 2008 // Make an inlining decision.
2005 if (TryInliningPoly(variants_[var_idx])) { 2009 if (TryInliningPoly(*info)) {
2006 TRACE_INLINING(TracePolyInlining(variants_[var_idx], total, "inlined")); 2010 TRACE_INLINING(TracePolyInlining(variants_, var_idx, total, "inlined"));
2007 inlined_variants_.Add(variants_[var_idx]); 2011 inlined_variants_.Add(&variants_[var_idx]);
2008 } else { 2012 } else {
2009 TRACE_INLINING( 2013 TRACE_INLINING(
2010 TracePolyInlining(variants_[var_idx], total, "not inlined")); 2014 TracePolyInlining(variants_, var_idx, total, "not inlined"));
2011 non_inlined_variants_->Add(variants_[var_idx]); 2015 non_inlined_variants_->Add(&variants_[var_idx]);
2012 } 2016 }
2013 } 2017 }
2014 2018
2015 // If there are no inlined variants, leave the call in place. 2019 // If there are no inlined variants, leave the call in place.
2016 if (inlined_variants_.is_empty()) return; 2020 if (inlined_variants_.is_empty()) return;
2017 2021
2018 // Now build a decision tree (a DAG because of shared inline variants) and 2022 // Now build a decision tree (a DAG because of shared inline variants) and
2019 // inline it at the call site. 2023 // inline it at the call site.
2020 TargetEntryInstr* entry = BuildDecisionGraph(); 2024 TargetEntryInstr* entry = BuildDecisionGraph();
2021 exit_collector_->ReplaceCall(entry); 2025 exit_collector_->ReplaceCall(entry);
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2262 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { 2266 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2263 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr( 2267 LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
2264 new (Z) Value(*array), ExternalTypedData::data_offset()); 2268 new (Z) Value(*array), ExternalTypedData::data_offset());
2265 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue); 2269 *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
2266 *array = elements; 2270 *array = elements;
2267 } 2271 }
2268 return array_cid; 2272 return array_cid;
2269 } 2273 }
2270 2274
2271 2275
2272 static Instruction* GetCheckClass(FlowGraph* flow_graph,
2273 Definition* to_check,
2274 const ICData& unary_checks,
2275 intptr_t deopt_id,
2276 TokenPosition token_pos) {
2277 if ((unary_checks.NumberOfUsedChecks() == 1) &&
2278 unary_checks.HasReceiverClassId(kSmiCid)) {
2279 return new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id, token_pos);
2280 }
2281 return new (Z) CheckClassInstr(new (Z) Value(to_check), deopt_id,
2282 unary_checks, token_pos);
2283 }
2284
2285
2286 static bool InlineGetIndexed(FlowGraph* flow_graph, 2276 static bool InlineGetIndexed(FlowGraph* flow_graph,
2287 MethodRecognizer::Kind kind, 2277 MethodRecognizer::Kind kind,
2288 Instruction* call, 2278 Instruction* call,
2289 Definition* receiver, 2279 Definition* receiver,
2290 TargetEntryInstr** entry, 2280 TargetEntryInstr** entry,
2291 Definition** last) { 2281 Definition** last) {
2292 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); 2282 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
2293 2283
2294 Definition* array = receiver; 2284 Definition* array = receiver;
2295 Definition* index = call->ArgumentAt(1); 2285 Definition* index = call->ArgumentAt(1);
(...skipping 30 matching lines...) Expand all
2326 return true; 2316 return true;
2327 } 2317 }
2328 2318
2329 2319
2330 static bool InlineSetIndexed(FlowGraph* flow_graph, 2320 static bool InlineSetIndexed(FlowGraph* flow_graph,
2331 MethodRecognizer::Kind kind, 2321 MethodRecognizer::Kind kind,
2332 const Function& target, 2322 const Function& target,
2333 Instruction* call, 2323 Instruction* call,
2334 Definition* receiver, 2324 Definition* receiver,
2335 TokenPosition token_pos, 2325 TokenPosition token_pos,
2336 const ICData& value_check, 2326 const Cids* value_check,
2337 TargetEntryInstr** entry, 2327 TargetEntryInstr** entry,
2338 Definition** last) { 2328 Definition** last) {
2339 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind); 2329 intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
2340 2330
2341 Definition* array = receiver; 2331 Definition* array = receiver;
2342 Definition* index = call->ArgumentAt(1); 2332 Definition* index = call->ArgumentAt(1);
2343 Definition* stored_value = call->ArgumentAt(2); 2333 Definition* stored_value = call->ArgumentAt(2);
2344 2334
2345 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(), 2335 *entry = new (Z) TargetEntryInstr(flow_graph->allocate_block_id(),
2346 call->GetBlock()->try_index()); 2336 call->GetBlock()->try_index());
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2421 StoreBarrierType needs_store_barrier = 2411 StoreBarrierType needs_store_barrier =
2422 (RawObject::IsTypedDataClassId(array_cid) || 2412 (RawObject::IsTypedDataClassId(array_cid) ||
2423 RawObject::IsTypedDataViewClassId(array_cid) || 2413 RawObject::IsTypedDataViewClassId(array_cid) ||
2424 RawObject::IsExternalTypedDataClassId(array_cid)) 2414 RawObject::IsExternalTypedDataClassId(array_cid))
2425 ? kNoStoreBarrier 2415 ? kNoStoreBarrier
2426 : kEmitStoreBarrier; 2416 : kEmitStoreBarrier;
2427 2417
2428 // No need to class check stores to Int32 and Uint32 arrays because 2418 // No need to class check stores to Int32 and Uint32 arrays because
2429 // we insert unboxing instructions below which include a class check. 2419 // we insert unboxing instructions below which include a class check.
2430 if ((array_cid != kTypedDataUint32ArrayCid) && 2420 if ((array_cid != kTypedDataUint32ArrayCid) &&
2431 (array_cid != kTypedDataInt32ArrayCid) && !value_check.IsNull()) { 2421 (array_cid != kTypedDataInt32ArrayCid) && value_check != NULL) {
2432 // No store barrier needed because checked value is a smi, an unboxed mint, 2422 // No store barrier needed because checked value is a smi, an unboxed mint,
2433 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. 2423 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
2434 needs_store_barrier = kNoStoreBarrier; 2424 needs_store_barrier = kNoStoreBarrier;
2435 Instruction* check = GetCheckClass(flow_graph, stored_value, value_check, 2425 Instruction* check = flow_graph->CreateCheckClass(
2436 call->deopt_id(), call->token_pos()); 2426 stored_value, *value_check, call->deopt_id(), call->token_pos());
2437 cursor = 2427 cursor =
2438 flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect); 2428 flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
2439 } 2429 }
2440 2430
2441 if (array_cid == kTypedDataFloat32ArrayCid) { 2431 if (array_cid == kTypedDataFloat32ArrayCid) {
2442 stored_value = new (Z) 2432 stored_value = new (Z)
2443 DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id()); 2433 DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
2444 cursor = 2434 cursor =
2445 flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue); 2435 flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue);
2446 } else if (array_cid == kTypedDataInt32ArrayCid) { 2436 } else if (array_cid == kTypedDataInt32ArrayCid) {
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
2689 // Extract the instance call so we can use the function_name in the stored 2679 // Extract the instance call so we can use the function_name in the stored
2690 // value check ICData. 2680 // value check ICData.
2691 InstanceCallInstr* i_call = NULL; 2681 InstanceCallInstr* i_call = NULL;
2692 if (call->IsPolymorphicInstanceCall()) { 2682 if (call->IsPolymorphicInstanceCall()) {
2693 i_call = call->AsPolymorphicInstanceCall()->instance_call(); 2683 i_call = call->AsPolymorphicInstanceCall()->instance_call();
2694 } else { 2684 } else {
2695 ASSERT(call->IsInstanceCall()); 2685 ASSERT(call->IsInstanceCall());
2696 i_call = call->AsInstanceCall(); 2686 i_call = call->AsInstanceCall();
2697 } 2687 }
2698 ASSERT(i_call != NULL); 2688 ASSERT(i_call != NULL);
2699 ICData& value_check = ICData::ZoneHandle(Z); 2689 Cids* value_check = NULL;
2700 switch (view_cid) { 2690 switch (view_cid) {
2701 case kTypedDataInt8ArrayCid: 2691 case kTypedDataInt8ArrayCid:
2702 case kTypedDataUint8ArrayCid: 2692 case kTypedDataUint8ArrayCid:
2703 case kTypedDataUint8ClampedArrayCid: 2693 case kTypedDataUint8ClampedArrayCid:
2704 case kExternalTypedDataUint8ArrayCid: 2694 case kExternalTypedDataUint8ArrayCid:
2705 case kExternalTypedDataUint8ClampedArrayCid: 2695 case kExternalTypedDataUint8ClampedArrayCid:
2706 case kTypedDataInt16ArrayCid: 2696 case kTypedDataInt16ArrayCid:
2707 case kTypedDataUint16ArrayCid: { 2697 case kTypedDataUint16ArrayCid: {
2708 // Check that value is always smi. 2698 // Check that value is always smi.
2709 value_check = ICData::New(flow_graph->function(), i_call->function_name(), 2699 value_check = Cids::CreateMonomorphic(Z, kSmiCid);
2710 Object::empty_array(), // Dummy args. descr.
2711 Thread::kNoDeoptId, 1, false);
2712 value_check.AddReceiverCheck(kSmiCid, target);
2713 break; 2700 break;
2714 } 2701 }
2715 case kTypedDataInt32ArrayCid: 2702 case kTypedDataInt32ArrayCid:
2716 case kTypedDataUint32ArrayCid: 2703 case kTypedDataUint32ArrayCid:
2717 // On 64-bit platforms assume that stored value is always a smi. 2704 // On 64-bit platforms assume that stored value is always a smi.
2718 if (kSmiBits >= 32) { 2705 if (kSmiBits >= 32) {
2719 value_check = 2706 value_check = Cids::CreateMonomorphic(Z, kSmiCid);
2720 ICData::New(flow_graph->function(), i_call->function_name(),
2721 Object::empty_array(), // Dummy args. descr.
2722 Thread::kNoDeoptId, 1, false);
2723 value_check.AddReceiverCheck(kSmiCid, target);
2724 } 2707 }
2725 break; 2708 break;
2726 case kTypedDataFloat32ArrayCid: 2709 case kTypedDataFloat32ArrayCid:
2727 case kTypedDataFloat64ArrayCid: { 2710 case kTypedDataFloat64ArrayCid: {
2728 // Check that value is always double. 2711 // Check that value is always double.
2729 value_check = ICData::New(flow_graph->function(), i_call->function_name(), 2712 value_check = Cids::CreateMonomorphic(Z, kDoubleCid);
2730 Object::empty_array(), // Dummy args. descr.
2731 Thread::kNoDeoptId, 1, false);
2732 value_check.AddReceiverCheck(kDoubleCid, target);
2733 break; 2713 break;
2734 } 2714 }
2735 case kTypedDataInt32x4ArrayCid: { 2715 case kTypedDataInt32x4ArrayCid: {
2736 // Check that value is always Int32x4. 2716 // Check that value is always Int32x4.
2737 value_check = ICData::New(flow_graph->function(), i_call->function_name(), 2717 value_check = Cids::CreateMonomorphic(Z, kInt32x4Cid);
2738 Object::empty_array(), // Dummy args. descr.
2739 Thread::kNoDeoptId, 1, false);
2740 value_check.AddReceiverCheck(kInt32x4Cid, target);
2741 break; 2718 break;
2742 } 2719 }
2743 case kTypedDataFloat32x4ArrayCid: { 2720 case kTypedDataFloat32x4ArrayCid: {
2744 // Check that value is always Float32x4. 2721 // Check that value is always Float32x4.
2745 value_check = ICData::New(flow_graph->function(), i_call->function_name(), 2722 value_check = Cids::CreateMonomorphic(Z, kFloat32x4Cid);
2746 Object::empty_array(), // Dummy args. descr.
2747 Thread::kNoDeoptId, 1, false);
2748 value_check.AddReceiverCheck(kFloat32x4Cid, target);
2749 break; 2723 break;
2750 } 2724 }
2751 default: 2725 default:
2752 // Array cids are already checked in the caller. 2726 // Array cids are already checked in the caller.
2753 UNREACHABLE(); 2727 UNREACHABLE();
2754 } 2728 }
2755 2729
2756 Definition* stored_value = call->ArgumentAt(2); 2730 Definition* stored_value = call->ArgumentAt(2);
2757 if (!value_check.IsNull()) { 2731 if (value_check != NULL) {
2758 Instruction* check = GetCheckClass(flow_graph, stored_value, value_check, 2732 Instruction* check = flow_graph->CreateCheckClass(
2759 call->deopt_id(), call->token_pos()); 2733 stored_value, *value_check, call->deopt_id(), call->token_pos());
2760 cursor = 2734 cursor =
2761 flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect); 2735 flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
2762 } 2736 }
2763 2737
2764 if (view_cid == kTypedDataFloat32ArrayCid) { 2738 if (view_cid == kTypedDataFloat32ArrayCid) {
2765 stored_value = new (Z) 2739 stored_value = new (Z)
2766 DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id()); 2740 DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
2767 cursor = 2741 cursor =
2768 flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue); 2742 flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue);
2769 } else if (view_cid == kTypedDataInt32ArrayCid) { 2743 } else if (view_cid == kTypedDataInt32ArrayCid) {
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2909 const intptr_t receiver_cid = class_ids[0]; 2883 const intptr_t receiver_cid = class_ids[0];
2910 2884
2911 TargetEntryInstr* entry; 2885 TargetEntryInstr* entry;
2912 Definition* last; 2886 Definition* last;
2913 if (FlowGraphInliner::TryInlineRecognizedMethod( 2887 if (FlowGraphInliner::TryInlineRecognizedMethod(
2914 flow_graph, receiver_cid, target, call, call->ArgumentAt(0), 2888 flow_graph, receiver_cid, target, call, call->ArgumentAt(0),
2915 call->token_pos(), *call->ic_data(), &entry, &last)) { 2889 call->token_pos(), *call->ic_data(), &entry, &last)) {
2916 // Insert receiver class check if needed. 2890 // Insert receiver class check if needed.
2917 if (MethodRecognizer::PolymorphicTarget(target) || 2891 if (MethodRecognizer::PolymorphicTarget(target) ||
2918 flow_graph->InstanceCallNeedsClassCheck(call, target.kind())) { 2892 flow_graph->InstanceCallNeedsClassCheck(call, target.kind())) {
2919 Instruction* check = GetCheckClass( 2893 Instruction* check = flow_graph->CreateCheckClass(
2920 flow_graph, call->ArgumentAt(0), 2894 call->ArgumentAt(0), *Cids::Create(Z, *call->ic_data(), 0),
2921 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()),
2922 call->deopt_id(), call->token_pos()); 2895 call->deopt_id(), call->token_pos());
2923 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect); 2896 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect);
2924 } 2897 }
2925 2898
2926 // Remove the original push arguments. 2899 // Remove the original push arguments.
2927 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2900 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2928 PushArgumentInstr* push = call->PushArgumentAt(i); 2901 PushArgumentInstr* push = call->PushArgumentAt(i);
2929 push->ReplaceUsesWith(push->value()->definition()); 2902 push->ReplaceUsesWith(push->value()->definition());
2930 push->RemoveFromGraph(); 2903 push->RemoveFromGraph();
2931 } 2904 }
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
3398 3371
3399 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, 3372 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph,
3400 intptr_t receiver_cid, 3373 intptr_t receiver_cid,
3401 const Function& target, 3374 const Function& target,
3402 Definition* call, 3375 Definition* call,
3403 Definition* receiver, 3376 Definition* receiver,
3404 TokenPosition token_pos, 3377 TokenPosition token_pos,
3405 const ICData& ic_data, 3378 const ICData& ic_data,
3406 TargetEntryInstr** entry, 3379 TargetEntryInstr** entry,
3407 Definition** last) { 3380 Definition** last) {
3408 ICData& value_check = ICData::ZoneHandle(Z);
3409 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); 3381 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
3410 switch (kind) { 3382 switch (kind) {
3411 // Recognized [] operators. 3383 // Recognized [] operators.
3412 case MethodRecognizer::kImmutableArrayGetIndexed: 3384 case MethodRecognizer::kImmutableArrayGetIndexed:
3413 case MethodRecognizer::kObjectArrayGetIndexed: 3385 case MethodRecognizer::kObjectArrayGetIndexed:
3414 case MethodRecognizer::kGrowableArrayGetIndexed: 3386 case MethodRecognizer::kGrowableArrayGetIndexed:
3415 case MethodRecognizer::kInt8ArrayGetIndexed: 3387 case MethodRecognizer::kInt8ArrayGetIndexed:
3416 case MethodRecognizer::kUint8ArrayGetIndexed: 3388 case MethodRecognizer::kUint8ArrayGetIndexed:
3417 case MethodRecognizer::kUint8ClampedArrayGetIndexed: 3389 case MethodRecognizer::kUint8ClampedArrayGetIndexed:
3418 case MethodRecognizer::kExternalUint8ArrayGetIndexed: 3390 case MethodRecognizer::kExternalUint8ArrayGetIndexed:
(...skipping 20 matching lines...) Expand all
3439 3411
3440 case MethodRecognizer::kInt64ArrayGetIndexed: 3412 case MethodRecognizer::kInt64ArrayGetIndexed:
3441 if (!ShouldInlineInt64ArrayOps()) { 3413 if (!ShouldInlineInt64ArrayOps()) {
3442 return false; 3414 return false;
3443 } 3415 }
3444 return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last); 3416 return InlineGetIndexed(flow_graph, kind, call, receiver, entry, last);
3445 // Recognized []= operators. 3417 // Recognized []= operators.
3446 case MethodRecognizer::kObjectArraySetIndexed: 3418 case MethodRecognizer::kObjectArraySetIndexed:
3447 case MethodRecognizer::kGrowableArraySetIndexed: 3419 case MethodRecognizer::kGrowableArraySetIndexed:
3448 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3420 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3449 token_pos, value_check, entry, last); 3421 token_pos, /* value_check = */ NULL, entry, last);
3450 case MethodRecognizer::kInt8ArraySetIndexed: 3422 case MethodRecognizer::kInt8ArraySetIndexed:
3451 case MethodRecognizer::kUint8ArraySetIndexed: 3423 case MethodRecognizer::kUint8ArraySetIndexed:
3452 case MethodRecognizer::kUint8ClampedArraySetIndexed: 3424 case MethodRecognizer::kUint8ClampedArraySetIndexed:
3453 case MethodRecognizer::kExternalUint8ArraySetIndexed: 3425 case MethodRecognizer::kExternalUint8ArraySetIndexed:
3454 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: 3426 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
3455 case MethodRecognizer::kInt16ArraySetIndexed: 3427 case MethodRecognizer::kInt16ArraySetIndexed:
3456 case MethodRecognizer::kUint16ArraySetIndexed: 3428 case MethodRecognizer::kUint16ArraySetIndexed: {
3457 // Optimistically assume Smi. 3429 // Optimistically assume Smi.
3458 if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) { 3430 if (ic_data.HasDeoptReason(ICData::kDeoptCheckSmi)) {
3459 // Optimistic assumption failed at least once. 3431 // Optimistic assumption failed at least once.
3460 return false; 3432 return false;
3461 } 3433 }
3462 value_check = ic_data.AsUnaryClassChecksForCid(kSmiCid, target); 3434 Cids* value_check = Cids::CreateMonomorphic(Z, kSmiCid);
3463 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3435 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3464 token_pos, value_check, entry, last); 3436 token_pos, value_check, entry, last);
3437 }
3465 case MethodRecognizer::kInt32ArraySetIndexed: 3438 case MethodRecognizer::kInt32ArraySetIndexed:
3466 case MethodRecognizer::kUint32ArraySetIndexed: { 3439 case MethodRecognizer::kUint32ArraySetIndexed: {
3467 // Value check not needed for Int32 and Uint32 arrays because they 3440 // Value check not needed for Int32 and Uint32 arrays because they
3468 // implicitly contain unboxing instructions which check for right type. 3441 // implicitly contain unboxing instructions which check for right type.
3469 ICData& value_check = ICData::Handle();
3470 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3442 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3471 token_pos, value_check, entry, last); 3443 token_pos, /* value_check = */ NULL, entry, last);
3472 } 3444 }
3473 case MethodRecognizer::kInt64ArraySetIndexed: 3445 case MethodRecognizer::kInt64ArraySetIndexed:
3474 if (!ShouldInlineInt64ArrayOps()) { 3446 if (!ShouldInlineInt64ArrayOps()) {
3475 return false; 3447 return false;
3476 } 3448 }
3477 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3449 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3478 token_pos, value_check, entry, last); 3450 token_pos, /* value_check = */ NULL, entry, last);
3479 case MethodRecognizer::kFloat32ArraySetIndexed: 3451 case MethodRecognizer::kFloat32ArraySetIndexed:
3480 case MethodRecognizer::kFloat64ArraySetIndexed: 3452 case MethodRecognizer::kFloat64ArraySetIndexed: {
3481 if (!CanUnboxDouble()) { 3453 if (!CanUnboxDouble()) {
3482 return false; 3454 return false;
3483 } 3455 }
3484 value_check = ic_data.AsUnaryClassChecksForCid(kDoubleCid, target); 3456 Cids* value_check = Cids::CreateMonomorphic(Z, kDoubleCid);
3485 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3457 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3486 token_pos, value_check, entry, last); 3458 token_pos, value_check, entry, last);
3487 case MethodRecognizer::kFloat32x4ArraySetIndexed: 3459 }
3460 case MethodRecognizer::kFloat32x4ArraySetIndexed: {
3488 if (!ShouldInlineSimd()) { 3461 if (!ShouldInlineSimd()) {
3489 return false; 3462 return false;
3490 } 3463 }
3491 value_check = ic_data.AsUnaryClassChecksForCid(kFloat32x4Cid, target); 3464 Cids* value_check = Cids::CreateMonomorphic(Z, kFloat32x4Cid);
3492
3493 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3465 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3494 token_pos, value_check, entry, last); 3466 token_pos, value_check, entry, last);
3495 case MethodRecognizer::kFloat64x2ArraySetIndexed: 3467 }
3468 case MethodRecognizer::kFloat64x2ArraySetIndexed: {
3496 if (!ShouldInlineSimd()) { 3469 if (!ShouldInlineSimd()) {
3497 return false; 3470 return false;
3498 } 3471 }
3499 value_check = ic_data.AsUnaryClassChecksForCid(kFloat64x2Cid, target); 3472 Cids* value_check = Cids::CreateMonomorphic(Z, kFloat64x2Cid);
3500 return InlineSetIndexed(flow_graph, kind, target, call, receiver, 3473 return InlineSetIndexed(flow_graph, kind, target, call, receiver,
3501 token_pos, value_check, entry, last); 3474 token_pos, value_check, entry, last);
3475 }
3502 case MethodRecognizer::kByteArrayBaseGetInt8: 3476 case MethodRecognizer::kByteArrayBaseGetInt8:
3503 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid, 3477 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
3504 kTypedDataInt8ArrayCid, entry, last); 3478 kTypedDataInt8ArrayCid, entry, last);
3505 case MethodRecognizer::kByteArrayBaseGetUint8: 3479 case MethodRecognizer::kByteArrayBaseGetUint8:
3506 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid, 3480 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
3507 kTypedDataUint8ArrayCid, entry, last); 3481 kTypedDataUint8ArrayCid, entry, last);
3508 case MethodRecognizer::kByteArrayBaseGetInt16: 3482 case MethodRecognizer::kByteArrayBaseGetInt16:
3509 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid, 3483 return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
3510 kTypedDataInt16ArrayCid, entry, last); 3484 kTypedDataInt16ArrayCid, entry, last);
3511 case MethodRecognizer::kByteArrayBaseGetUint16: 3485 case MethodRecognizer::kByteArrayBaseGetUint16:
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
3809 } 3783 }
3810 3784
3811 default: 3785 default:
3812 return false; 3786 return false;
3813 } 3787 }
3814 } 3788 }
3815 3789
3816 3790
3817 } // namespace dart 3791 } // namespace dart
3818 #endif // !defined(DART_PRECOMPILED_RUNTIME) 3792 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698