| OLD | NEW |
| 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 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 223 } |
| 224 if (smi_shift_left == NULL) return; | 224 if (smi_shift_left == NULL) return; |
| 225 | 225 |
| 226 // Pattern recognized. | 226 // Pattern recognized. |
| 227 smi_shift_left->set_is_truncating(true); | 227 smi_shift_left->set_is_truncating(true); |
| 228 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); | 228 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); |
| 229 if (bit_and_instr->IsBinaryMintOp()) { | 229 if (bit_and_instr->IsBinaryMintOp()) { |
| 230 // Replace Mint op with Smi op. | 230 // Replace Mint op with Smi op. |
| 231 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( | 231 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( |
| 232 Token::kBIT_AND, | 232 Token::kBIT_AND, |
| 233 bit_and_instr->AsBinaryMintOp()->instance_call(), | |
| 234 new Value(left_instr), | 233 new Value(left_instr), |
| 235 new Value(right_instr)); | 234 new Value(right_instr), |
| 235 bit_and_instr->deopt_id()); |
| 236 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 236 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 | 239 |
| 240 | 240 |
| 241 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the | 241 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the |
| 242 // shift can be a truncating Smi shift-left and result is always Smi. | 242 // shift can be a truncating Smi shift-left and result is always Smi. |
| 243 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { | 243 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { |
| 244 if (!FLAG_truncating_left_shift) return; | 244 if (!FLAG_truncating_left_shift) return; |
| 245 ASSERT(current_iterator_ == NULL); | 245 ASSERT(current_iterator_ == NULL); |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 CheckArrayBoundInstr::LengthOffsetFor(class_id), | 727 CheckArrayBoundInstr::LengthOffsetFor(class_id), |
| 728 Type::ZoneHandle(Type::SmiType()), | 728 Type::ZoneHandle(Type::SmiType()), |
| 729 is_immutable); | 729 is_immutable); |
| 730 length->set_result_cid(kSmiCid); | 730 length->set_result_cid(kSmiCid); |
| 731 length->set_recognized_kind( | 731 length->set_recognized_kind( |
| 732 LoadFieldInstr::RecognizedKindFromArrayCid(class_id)); | 732 LoadFieldInstr::RecognizedKindFromArrayCid(class_id)); |
| 733 InsertBefore(call, length, NULL, Definition::kValue); | 733 InsertBefore(call, length, NULL, Definition::kValue); |
| 734 InsertBefore(call, | 734 InsertBefore(call, |
| 735 new CheckArrayBoundInstr(new Value(length), | 735 new CheckArrayBoundInstr(new Value(length), |
| 736 new Value(*index), | 736 new Value(*index), |
| 737 call), | 737 call->deopt_id()), |
| 738 call->env(), | 738 call->env(), |
| 739 Definition::kEffect); | 739 Definition::kEffect); |
| 740 | 740 |
| 741 if (class_id == kGrowableObjectArrayCid) { | 741 if (class_id == kGrowableObjectArrayCid) { |
| 742 // Insert data elements load. | 742 // Insert data elements load. |
| 743 LoadFieldInstr* elements = | 743 LoadFieldInstr* elements = |
| 744 new LoadFieldInstr(new Value(*array), | 744 new LoadFieldInstr(new Value(*array), |
| 745 GrowableObjectArray::data_offset(), | 745 GrowableObjectArray::data_offset(), |
| 746 Type::ZoneHandle(Type::DynamicType())); | 746 Type::ZoneHandle(Type::DynamicType())); |
| 747 elements->set_result_cid(kArrayCid); | 747 elements->set_result_cid(kArrayCid); |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1099 | 1099 |
| 1100 ASSERT(call->ArgumentCount() == 2); | 1100 ASSERT(call->ArgumentCount() == 2); |
| 1101 Definition* left = call->ArgumentAt(0); | 1101 Definition* left = call->ArgumentAt(0); |
| 1102 Definition* right = call->ArgumentAt(1); | 1102 Definition* right = call->ArgumentAt(1); |
| 1103 if (operands_type == kDoubleCid) { | 1103 if (operands_type == kDoubleCid) { |
| 1104 // Check that either left or right are not a smi. Result of a | 1104 // Check that either left or right are not a smi. Result of a |
| 1105 // binary operation with two smis is a smi not a double. | 1105 // binary operation with two smis is a smi not a double. |
| 1106 InsertBefore(call, | 1106 InsertBefore(call, |
| 1107 new CheckEitherNonSmiInstr(new Value(left), | 1107 new CheckEitherNonSmiInstr(new Value(left), |
| 1108 new Value(right), | 1108 new Value(right), |
| 1109 call), | 1109 call->deopt_id()), |
| 1110 call->env(), | 1110 call->env(), |
| 1111 Definition::kEffect); | 1111 Definition::kEffect); |
| 1112 | 1112 |
| 1113 BinaryDoubleOpInstr* double_bin_op = | 1113 BinaryDoubleOpInstr* double_bin_op = |
| 1114 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), | 1114 new BinaryDoubleOpInstr(op_kind, new Value(left), new Value(right), |
| 1115 call); | 1115 call->deopt_id()); |
| 1116 ReplaceCall(call, double_bin_op); | 1116 ReplaceCall(call, double_bin_op); |
| 1117 } else if (operands_type == kMintCid) { | 1117 } else if (operands_type == kMintCid) { |
| 1118 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; | 1118 if (!FlowGraphCompiler::SupportsUnboxedMints()) return false; |
| 1119 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { | 1119 if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) { |
| 1120 ShiftMintOpInstr* shift_op = | 1120 ShiftMintOpInstr* shift_op = |
| 1121 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), | 1121 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1122 call); | 1122 call->deopt_id()); |
| 1123 ReplaceCall(call, shift_op); | 1123 ReplaceCall(call, shift_op); |
| 1124 } else { | 1124 } else { |
| 1125 BinaryMintOpInstr* bin_op = | 1125 BinaryMintOpInstr* bin_op = |
| 1126 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 1126 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
| 1127 call); | 1127 call->deopt_id()); |
| 1128 ReplaceCall(call, bin_op); | 1128 ReplaceCall(call, bin_op); |
| 1129 } | 1129 } |
| 1130 } else if (operands_type == kFloat32x4Cid) { | 1130 } else if (operands_type == kFloat32x4Cid) { |
| 1131 // Type check left. | 1131 // Type check left. |
| 1132 AddCheckClass(left, | 1132 AddCheckClass(left, |
| 1133 ICData::ZoneHandle( | 1133 ICData::ZoneHandle( |
| 1134 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1134 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1135 call->deopt_id(), | 1135 call->deopt_id(), |
| 1136 call->env(), | 1136 call->env(), |
| 1137 call); | 1137 call); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1178 | 1178 |
| 1179 // Insert smi check and attach a copy of the original environment | 1179 // Insert smi check and attach a copy of the original environment |
| 1180 // because the smi operation can still deoptimize. | 1180 // because the smi operation can still deoptimize. |
| 1181 InsertBefore(call, | 1181 InsertBefore(call, |
| 1182 new CheckSmiInstr(new Value(left), call->deopt_id()), | 1182 new CheckSmiInstr(new Value(left), call->deopt_id()), |
| 1183 call->env(), | 1183 call->env(), |
| 1184 Definition::kEffect); | 1184 Definition::kEffect); |
| 1185 ConstantInstr* constant = | 1185 ConstantInstr* constant = |
| 1186 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1))); | 1186 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1))); |
| 1187 BinarySmiOpInstr* bin_op = | 1187 BinarySmiOpInstr* bin_op = |
| 1188 new BinarySmiOpInstr(Token::kBIT_AND, call, | 1188 new BinarySmiOpInstr(Token::kBIT_AND, |
| 1189 new Value(left), | 1189 new Value(left), |
| 1190 new Value(constant)); | 1190 new Value(constant), |
| 1191 call->deopt_id()); |
| 1191 ReplaceCall(call, bin_op); | 1192 ReplaceCall(call, bin_op); |
| 1192 } else { | 1193 } else { |
| 1193 ASSERT(operands_type == kSmiCid); | 1194 ASSERT(operands_type == kSmiCid); |
| 1194 // Insert two smi checks and attach a copy of the original | 1195 // Insert two smi checks and attach a copy of the original |
| 1195 // environment because the smi operation can still deoptimize. | 1196 // environment because the smi operation can still deoptimize. |
| 1196 AddCheckSmi(left, call->deopt_id(), call->env(), call); | 1197 AddCheckSmi(left, call->deopt_id(), call->env(), call); |
| 1197 AddCheckSmi(right, call->deopt_id(), call->env(), call); | 1198 AddCheckSmi(right, call->deopt_id(), call->env(), call); |
| 1198 if (left->IsConstant() && | 1199 if (left->IsConstant() && |
| 1199 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { | 1200 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { |
| 1200 // Constant should be on the right side. | 1201 // Constant should be on the right side. |
| 1201 Definition* temp = left; | 1202 Definition* temp = left; |
| 1202 left = right; | 1203 left = right; |
| 1203 right = temp; | 1204 right = temp; |
| 1204 } | 1205 } |
| 1205 BinarySmiOpInstr* bin_op = | 1206 BinarySmiOpInstr* bin_op = |
| 1206 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); | 1207 new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), |
| 1208 call->deopt_id()); |
| 1207 ReplaceCall(call, bin_op); | 1209 ReplaceCall(call, bin_op); |
| 1208 } | 1210 } |
| 1209 return true; | 1211 return true; |
| 1210 } | 1212 } |
| 1211 | 1213 |
| 1212 | 1214 |
| 1213 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, | 1215 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, |
| 1214 Token::Kind op_kind) { | 1216 Token::Kind op_kind) { |
| 1215 ASSERT(call->ArgumentCount() == 1); | 1217 ASSERT(call->ArgumentCount() == 1); |
| 1216 Definition* input = call->ArgumentAt(0); | 1218 Definition* input = call->ArgumentAt(0); |
| 1217 Definition* unary_op = NULL; | 1219 Definition* unary_op = NULL; |
| 1218 if (HasOnlyOneSmi(*call->ic_data())) { | 1220 if (HasOnlyOneSmi(*call->ic_data())) { |
| 1219 InsertBefore(call, | 1221 InsertBefore(call, |
| 1220 new CheckSmiInstr(new Value(input), call->deopt_id()), | 1222 new CheckSmiInstr(new Value(input), call->deopt_id()), |
| 1221 call->env(), | 1223 call->env(), |
| 1222 Definition::kEffect); | 1224 Definition::kEffect); |
| 1223 unary_op = new UnarySmiOpInstr(op_kind, call, new Value(input)); | 1225 unary_op = new UnarySmiOpInstr(op_kind, new Value(input), call->deopt_id()); |
| 1224 } else if ((op_kind == Token::kBIT_NOT) && | 1226 } else if ((op_kind == Token::kBIT_NOT) && |
| 1225 HasOnlySmiOrMint(*call->ic_data()) && | 1227 HasOnlySmiOrMint(*call->ic_data()) && |
| 1226 FlowGraphCompiler::SupportsUnboxedMints()) { | 1228 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1227 unary_op = new UnaryMintOpInstr(op_kind, new Value(input), call); | 1229 unary_op = new UnaryMintOpInstr( |
| 1230 op_kind, new Value(input), call->deopt_id()); |
| 1228 } else if (HasOnlyOneDouble(*call->ic_data()) && | 1231 } else if (HasOnlyOneDouble(*call->ic_data()) && |
| 1229 (op_kind == Token::kNEGATE)) { | 1232 (op_kind == Token::kNEGATE)) { |
| 1230 AddReceiverCheck(call); | 1233 AddReceiverCheck(call); |
| 1231 ConstantInstr* minus_one = | 1234 ConstantInstr* minus_one = |
| 1232 flow_graph()->GetConstant(Double::ZoneHandle(Double::NewCanonical(-1))); | 1235 flow_graph()->GetConstant(Double::ZoneHandle(Double::NewCanonical(-1))); |
| 1233 unary_op = new BinaryDoubleOpInstr(Token::kMUL, | 1236 unary_op = new BinaryDoubleOpInstr(Token::kMUL, |
| 1234 new Value(input), | 1237 new Value(input), |
| 1235 new Value(minus_one), | 1238 new Value(minus_one), |
| 1236 call); | 1239 call->deopt_id()); |
| 1237 } | 1240 } |
| 1238 if (unary_op == NULL) return false; | 1241 if (unary_op == NULL) return false; |
| 1239 | 1242 |
| 1240 ReplaceCall(call, unary_op); | 1243 ReplaceCall(call, unary_op); |
| 1241 return true; | 1244 return true; |
| 1242 } | 1245 } |
| 1243 | 1246 |
| 1244 | 1247 |
| 1245 // Using field class | 1248 // Using field class |
| 1246 static RawField* GetField(intptr_t class_id, const String& field_name) { | 1249 static RawField* GetField(intptr_t class_id, const String& field_name) { |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 skip_check = constant_index.IsSmi() && | 1611 skip_check = constant_index.IsSmi() && |
| 1609 (Smi::Cast(constant_index).Value() < constant_string.Length()); | 1612 (Smi::Cast(constant_index).Value() < constant_string.Length()); |
| 1610 } | 1613 } |
| 1611 if (!skip_check) { | 1614 if (!skip_check) { |
| 1612 // Insert bounds check. | 1615 // Insert bounds check. |
| 1613 LoadFieldInstr* length = BuildLoadStringLength(str); | 1616 LoadFieldInstr* length = BuildLoadStringLength(str); |
| 1614 InsertBefore(call, length, NULL, Definition::kValue); | 1617 InsertBefore(call, length, NULL, Definition::kValue); |
| 1615 InsertBefore(call, | 1618 InsertBefore(call, |
| 1616 new CheckArrayBoundInstr(new Value(length), | 1619 new CheckArrayBoundInstr(new Value(length), |
| 1617 new Value(index), | 1620 new Value(index), |
| 1618 call), | 1621 call->deopt_id()), |
| 1619 call->env(), | 1622 call->env(), |
| 1620 Definition::kEffect); | 1623 Definition::kEffect); |
| 1621 } | 1624 } |
| 1622 return new LoadIndexedInstr(new Value(str), | 1625 return new LoadIndexedInstr(new Value(str), |
| 1623 new Value(index), | 1626 new Value(index), |
| 1624 FlowGraphCompiler::ElementSizeFor(cid), | 1627 FlowGraphCompiler::ElementSizeFor(cid), |
| 1625 cid, | 1628 cid, |
| 1626 Isolate::kNoDeoptId); // Can't deoptimize. | 1629 Isolate::kNoDeoptId); // Can't deoptimize. |
| 1627 } | 1630 } |
| 1628 | 1631 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 AddReceiverCheck(call); | 1766 AddReceiverCheck(call); |
| 1764 ASSERT(call->HasICData()); | 1767 ASSERT(call->HasICData()); |
| 1765 const ICData& ic_data = *call->ic_data(); | 1768 const ICData& ic_data = *call->ic_data(); |
| 1766 Definition* input = call->ArgumentAt(0); | 1769 Definition* input = call->ArgumentAt(0); |
| 1767 Definition* d2i_instr = NULL; | 1770 Definition* d2i_instr = NULL; |
| 1768 if (ic_data.deopt_reason() == kDeoptDoubleToSmi) { | 1771 if (ic_data.deopt_reason() == kDeoptDoubleToSmi) { |
| 1769 // Do not repeatedly deoptimize because result didn't fit into Smi. | 1772 // Do not repeatedly deoptimize because result didn't fit into Smi. |
| 1770 d2i_instr = new DoubleToIntegerInstr(new Value(input), call); | 1773 d2i_instr = new DoubleToIntegerInstr(new Value(input), call); |
| 1771 } else { | 1774 } else { |
| 1772 // Optimistically assume result fits into Smi. | 1775 // Optimistically assume result fits into Smi. |
| 1773 d2i_instr = new DoubleToSmiInstr(new Value(input), call); | 1776 d2i_instr = new DoubleToSmiInstr(new Value(input), call->deopt_id()); |
| 1774 } | 1777 } |
| 1775 ReplaceCall(call, d2i_instr); | 1778 ReplaceCall(call, d2i_instr); |
| 1776 return true; | 1779 return true; |
| 1777 } | 1780 } |
| 1778 case MethodRecognizer::kDoubleMod: | 1781 case MethodRecognizer::kDoubleMod: |
| 1779 case MethodRecognizer::kDoublePow: | 1782 case MethodRecognizer::kDoublePow: |
| 1780 case MethodRecognizer::kDoubleRound: | 1783 case MethodRecognizer::kDoubleRound: |
| 1781 ReplaceWithMathCFunction(call, recognized_kind); | 1784 ReplaceWithMathCFunction(call, recognized_kind); |
| 1782 return true; | 1785 return true; |
| 1783 case MethodRecognizer::kDoubleTruncate: | 1786 case MethodRecognizer::kDoubleTruncate: |
| 1784 case MethodRecognizer::kDoubleFloor: | 1787 case MethodRecognizer::kDoubleFloor: |
| 1785 case MethodRecognizer::kDoubleCeil: | 1788 case MethodRecognizer::kDoubleCeil: |
| 1786 if (!CPUFeatures::double_truncate_round_supported()) { | 1789 if (!CPUFeatures::double_truncate_round_supported()) { |
| 1787 ReplaceWithMathCFunction(call, recognized_kind); | 1790 ReplaceWithMathCFunction(call, recognized_kind); |
| 1788 } else { | 1791 } else { |
| 1789 AddReceiverCheck(call); | 1792 AddReceiverCheck(call); |
| 1790 DoubleToDoubleInstr* d2d_instr = | 1793 DoubleToDoubleInstr* d2d_instr = |
| 1791 new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)), | 1794 new DoubleToDoubleInstr(new Value(call->ArgumentAt(0)), |
| 1792 call, | 1795 recognized_kind, call->deopt_id()); |
| 1793 recognized_kind); | |
| 1794 ReplaceCall(call, d2d_instr); | 1796 ReplaceCall(call, d2d_instr); |
| 1795 } | 1797 } |
| 1796 return true; | 1798 return true; |
| 1797 default: | 1799 default: |
| 1798 // Unsupported method. | 1800 // Unsupported method. |
| 1799 return false; | 1801 return false; |
| 1800 } | 1802 } |
| 1801 } | 1803 } |
| 1802 | 1804 |
| 1803 if (IsSupportedByteArrayViewCid(class_ids[0]) && | 1805 if (IsSupportedByteArrayViewCid(class_ids[0]) && |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 length->set_recognized_kind( | 2234 length->set_recognized_kind( |
| 2233 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid)); | 2235 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid)); |
| 2234 InsertBefore(call, length, NULL, Definition::kValue); | 2236 InsertBefore(call, length, NULL, Definition::kValue); |
| 2235 | 2237 |
| 2236 // len_in_bytes = length * kBytesPerElement(receiver) | 2238 // len_in_bytes = length * kBytesPerElement(receiver) |
| 2237 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); | 2239 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); |
| 2238 ConstantInstr* bytes_per_element = | 2240 ConstantInstr* bytes_per_element = |
| 2239 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); | 2241 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); |
| 2240 BinarySmiOpInstr* len_in_bytes = | 2242 BinarySmiOpInstr* len_in_bytes = |
| 2241 new BinarySmiOpInstr(Token::kMUL, | 2243 new BinarySmiOpInstr(Token::kMUL, |
| 2242 call, | |
| 2243 new Value(length), | 2244 new Value(length), |
| 2244 new Value(bytes_per_element)); | 2245 new Value(bytes_per_element), |
| 2246 call->deopt_id()); |
| 2245 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); | 2247 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); |
| 2246 | 2248 |
| 2247 // Check byte_index < len_in_bytes. | 2249 // Check byte_index < len_in_bytes. |
| 2248 InsertBefore(call, | 2250 InsertBefore(call, |
| 2249 new CheckArrayBoundInstr(new Value(len_in_bytes), | 2251 new CheckArrayBoundInstr(new Value(len_in_bytes), |
| 2250 new Value(byte_index), | 2252 new Value(byte_index), |
| 2251 call), | 2253 call->deopt_id()), |
| 2252 call->env(), | 2254 call->env(), |
| 2253 Definition::kEffect); | 2255 Definition::kEffect); |
| 2254 | 2256 |
| 2255 // Insert load of elements for external typed arrays. | 2257 // Insert load of elements for external typed arrays. |
| 2256 if (RawObject::IsExternalTypedDataClassId(receiver_cid)) { | 2258 if (RawObject::IsExternalTypedDataClassId(receiver_cid)) { |
| 2257 LoadUntaggedInstr* elements = | 2259 LoadUntaggedInstr* elements = |
| 2258 new LoadUntaggedInstr(new Value(*array), | 2260 new LoadUntaggedInstr(new Value(*array), |
| 2259 ExternalTypedData::data_offset()); | 2261 ExternalTypedData::data_offset()); |
| 2260 InsertBefore(call, elements, NULL, Definition::kValue); | 2262 InsertBefore(call, elements, NULL, Definition::kValue); |
| 2261 *array = elements; | 2263 *array = elements; |
| (...skipping 4922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7184 | 7186 |
| 7185 // Insert materializations at environment uses. | 7187 // Insert materializations at environment uses. |
| 7186 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 7188 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 7187 for (intptr_t i = 0; i < exits.length(); i++) { | 7189 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7188 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 7190 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 7189 } | 7191 } |
| 7190 } | 7192 } |
| 7191 | 7193 |
| 7192 | 7194 |
| 7193 } // namespace dart | 7195 } // namespace dart |
| OLD | NEW |