| 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 if (function.IsNull()) { | 126 if (function.IsNull()) { |
| 127 return false; | 127 return false; |
| 128 } | 128 } |
| 129 // Create new ICData, do not modify the one attached to the instruction | 129 // Create new ICData, do not modify the one attached to the instruction |
| 130 // since it is attached to the assembly instruction itself. | 130 // since it is attached to the assembly instruction itself. |
| 131 // TODO(srdjan): Prevent modification of ICData object that is | 131 // TODO(srdjan): Prevent modification of ICData object that is |
| 132 // referenced in assembly code. | 132 // referenced in assembly code. |
| 133 ICData& ic_data = ICData::ZoneHandle(ICData::New( | 133 ICData& ic_data = ICData::ZoneHandle(ICData::New( |
| 134 flow_graph_->parsed_function().function(), | 134 flow_graph_->parsed_function().function(), |
| 135 call->function_name(), | 135 call->function_name(), |
| 136 Object::null_array(), // Dummy argument descriptor. | 136 Object::empty_array(), // Dummy argument descriptor. |
| 137 call->deopt_id(), | 137 call->deopt_id(), |
| 138 class_ids.length())); | 138 class_ids.length())); |
| 139 ic_data.AddReceiverCheck(class_ids[0], function); | 139 ic_data.AddReceiverCheck(class_ids[0], function); |
| 140 call->set_ic_data(&ic_data); | 140 call->set_ic_data(&ic_data); |
| 141 return true; | 141 return true; |
| 142 } | 142 } |
| 143 return false; | 143 return false; |
| 144 } | 144 } |
| 145 | 145 |
| 146 | 146 |
| 147 static const ICData& SpecializeICData(const ICData& ic_data, intptr_t cid) { | 147 static const ICData& SpecializeICData(const ICData& ic_data, intptr_t cid) { |
| 148 ASSERT(ic_data.num_args_tested() == 1); | 148 ASSERT(ic_data.num_args_tested() == 1); |
| 149 | 149 |
| 150 if ((ic_data.NumberOfChecks() == 1) && | 150 if ((ic_data.NumberOfChecks() == 1) && |
| 151 (ic_data.GetReceiverClassIdAt(0) == cid)) { | 151 (ic_data.GetReceiverClassIdAt(0) == cid)) { |
| 152 return ic_data; // Nothing to do | 152 return ic_data; // Nothing to do |
| 153 } | 153 } |
| 154 | 154 |
| 155 const ICData& new_ic_data = ICData::ZoneHandle(ICData::New( | 155 const ICData& new_ic_data = ICData::ZoneHandle(ICData::New( |
| 156 Function::Handle(ic_data.function()), | 156 Function::Handle(ic_data.function()), |
| 157 String::Handle(ic_data.target_name()), | 157 String::Handle(ic_data.target_name()), |
| 158 Object::null_array(), // Dummy argument descriptor. | 158 Object::empty_array(), // Dummy argument descriptor. |
| 159 ic_data.deopt_id(), | 159 ic_data.deopt_id(), |
| 160 ic_data.num_args_tested())); | 160 ic_data.num_args_tested())); |
| 161 | 161 |
| 162 const Function& function = | 162 const Function& function = |
| 163 Function::Handle(ic_data.GetTargetForReceiverClassId(cid)); | 163 Function::Handle(ic_data.GetTargetForReceiverClassId(cid)); |
| 164 if (!function.IsNull()) { | 164 if (!function.IsNull()) { |
| 165 new_ic_data.AddReceiverCheck(cid, function); | 165 new_ic_data.AddReceiverCheck(cid, function); |
| 166 } | 166 } |
| 167 | 167 |
| 168 return new_ic_data; | 168 return new_ic_data; |
| (...skipping 1736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 call, class_ids[0], kTypedDataFloat32ArrayCid); | 1905 call, class_ids[0], kTypedDataFloat32ArrayCid); |
| 1906 case MethodRecognizer::kByteArrayBaseGetFloat64: | 1906 case MethodRecognizer::kByteArrayBaseGetFloat64: |
| 1907 return BuildByteArrayViewLoad( | 1907 return BuildByteArrayViewLoad( |
| 1908 call, class_ids[0], kTypedDataFloat64ArrayCid); | 1908 call, class_ids[0], kTypedDataFloat64ArrayCid); |
| 1909 case MethodRecognizer::kByteArrayBaseGetFloat32x4: | 1909 case MethodRecognizer::kByteArrayBaseGetFloat32x4: |
| 1910 return BuildByteArrayViewLoad( | 1910 return BuildByteArrayViewLoad( |
| 1911 call, class_ids[0], kTypedDataFloat32x4ArrayCid); | 1911 call, class_ids[0], kTypedDataFloat32x4ArrayCid); |
| 1912 | 1912 |
| 1913 // ByteArray setters. | 1913 // ByteArray setters. |
| 1914 case MethodRecognizer::kByteArrayBaseSetInt8: | 1914 case MethodRecognizer::kByteArrayBaseSetInt8: |
| 1915 return BuildByteArrayViewStore( | 1915 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); |
| 1916 call, class_ids[0], kTypedDataInt8ArrayCid); | |
| 1917 case MethodRecognizer::kByteArrayBaseSetUint8: | 1916 case MethodRecognizer::kByteArrayBaseSetUint8: |
| 1918 return BuildByteArrayViewStore( | 1917 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); |
| 1919 call, class_ids[0], kTypedDataUint8ArrayCid); | |
| 1920 case MethodRecognizer::kByteArrayBaseSetInt16: | 1918 case MethodRecognizer::kByteArrayBaseSetInt16: |
| 1921 return BuildByteArrayViewStore( | 1919 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); |
| 1922 call, class_ids[0], kTypedDataInt16ArrayCid); | |
| 1923 case MethodRecognizer::kByteArrayBaseSetUint16: | 1920 case MethodRecognizer::kByteArrayBaseSetUint16: |
| 1924 return BuildByteArrayViewStore( | 1921 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); |
| 1925 call, class_ids[0], kTypedDataUint16ArrayCid); | |
| 1926 case MethodRecognizer::kByteArrayBaseSetInt32: | 1922 case MethodRecognizer::kByteArrayBaseSetInt32: |
| 1927 return BuildByteArrayViewStore( | 1923 return BuildByteArrayViewStore(call, kTypedDataInt32ArrayCid); |
| 1928 call, class_ids[0], kTypedDataInt32ArrayCid); | |
| 1929 case MethodRecognizer::kByteArrayBaseSetUint32: | 1924 case MethodRecognizer::kByteArrayBaseSetUint32: |
| 1930 return BuildByteArrayViewStore( | 1925 return BuildByteArrayViewStore(call, kTypedDataUint32ArrayCid); |
| 1931 call, class_ids[0], kTypedDataUint32ArrayCid); | |
| 1932 case MethodRecognizer::kByteArrayBaseSetFloat32: | 1926 case MethodRecognizer::kByteArrayBaseSetFloat32: |
| 1933 return BuildByteArrayViewStore( | 1927 return BuildByteArrayViewStore(call, kTypedDataFloat32ArrayCid); |
| 1934 call, class_ids[0], kTypedDataFloat32ArrayCid); | |
| 1935 case MethodRecognizer::kByteArrayBaseSetFloat64: | 1928 case MethodRecognizer::kByteArrayBaseSetFloat64: |
| 1936 return BuildByteArrayViewStore( | 1929 return BuildByteArrayViewStore(call, kTypedDataFloat64ArrayCid); |
| 1937 call, class_ids[0], kTypedDataFloat64ArrayCid); | |
| 1938 case MethodRecognizer::kByteArrayBaseSetFloat32x4: | 1930 case MethodRecognizer::kByteArrayBaseSetFloat32x4: |
| 1939 return BuildByteArrayViewStore( | 1931 return BuildByteArrayViewStore(call, kTypedDataFloat32x4ArrayCid); |
| 1940 call, class_ids[0], kTypedDataFloat32x4ArrayCid); | |
| 1941 default: | 1932 default: |
| 1942 // Unsupported method. | 1933 // Unsupported method. |
| 1943 return false; | 1934 return false; |
| 1944 } | 1935 } |
| 1945 } | 1936 } |
| 1946 | 1937 |
| 1947 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 1938 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
| 1948 return TryInlineFloat32x4Method(call, recognized_kind); | 1939 return TryInlineFloat32x4Method(call, recognized_kind); |
| 1949 } | 1940 } |
| 1950 | 1941 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), | 2247 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), |
| 2257 new Value(byte_index), | 2248 new Value(byte_index), |
| 2258 1, // Index scale. | 2249 1, // Index scale. |
| 2259 view_cid, | 2250 view_cid, |
| 2260 deopt_id); | 2251 deopt_id); |
| 2261 ReplaceCall(call, array_op); | 2252 ReplaceCall(call, array_op); |
| 2262 return true; | 2253 return true; |
| 2263 } | 2254 } |
| 2264 | 2255 |
| 2265 | 2256 |
| 2266 bool FlowGraphOptimizer::BuildByteArrayViewStore( | 2257 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, |
| 2267 InstanceCallInstr* call, | 2258 intptr_t view_cid) { |
| 2268 intptr_t receiver_cid, | |
| 2269 intptr_t view_cid) { | |
| 2270 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { | 2259 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { |
| 2271 return false; | 2260 return false; |
| 2272 } | 2261 } |
| 2262 ASSERT(call->HasICData()); |
| 2263 Function& target = Function::Handle(); |
| 2264 GrowableArray<intptr_t> class_ids; |
| 2265 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2266 const intptr_t receiver_cid = class_ids[0]; |
| 2267 |
| 2273 Definition* array = call->ArgumentAt(0); | 2268 Definition* array = call->ArgumentAt(0); |
| 2274 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); | 2269 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); |
| 2275 ICData& value_check = ICData::ZoneHandle(); | 2270 ICData& value_check = ICData::ZoneHandle(); |
| 2276 switch (view_cid) { | 2271 switch (view_cid) { |
| 2277 case kTypedDataInt8ArrayCid: | 2272 case kTypedDataInt8ArrayCid: |
| 2278 case kTypedDataUint8ArrayCid: | 2273 case kTypedDataUint8ArrayCid: |
| 2279 case kTypedDataUint8ClampedArrayCid: | 2274 case kTypedDataUint8ClampedArrayCid: |
| 2280 case kExternalTypedDataUint8ArrayCid: | 2275 case kExternalTypedDataUint8ArrayCid: |
| 2281 case kExternalTypedDataUint8ClampedArrayCid: | 2276 case kExternalTypedDataUint8ClampedArrayCid: |
| 2282 case kTypedDataInt16ArrayCid: | 2277 case kTypedDataInt16ArrayCid: |
| 2283 case kTypedDataUint16ArrayCid: { | 2278 case kTypedDataUint16ArrayCid: { |
| 2284 // Check that value is always smi. | 2279 // Check that value is always smi. |
| 2285 value_check = ICData::New(Function::Handle(), | 2280 value_check = ICData::New(flow_graph_->parsed_function().function(), |
| 2286 Object::null_string(), | 2281 call->function_name(), |
| 2287 Object::null_array(), | 2282 Object::empty_array(), // Dummy args. descr. |
| 2288 Isolate::kNoDeoptId, | 2283 Isolate::kNoDeoptId, |
| 2289 1); | 2284 1); |
| 2290 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | 2285 value_check.AddReceiverCheck(kSmiCid, target); |
| 2291 break; | 2286 break; |
| 2292 } | 2287 } |
| 2293 case kTypedDataInt32ArrayCid: | 2288 case kTypedDataInt32ArrayCid: |
| 2294 case kTypedDataUint32ArrayCid: | 2289 case kTypedDataUint32ArrayCid: |
| 2295 // We don't have ICData for the value stored, so we optimistically assume | 2290 // We don't have ICData for the value stored, so we optimistically assume |
| 2296 // smis first. If we ever deoptimized here, we require to unbox the value | 2291 // smis first. If we ever deoptimized here, we require to unbox the value |
| 2297 // before storing to handle the mint case, too. | 2292 // before storing to handle the mint case, too. |
| 2298 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { | 2293 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { |
| 2299 value_check = ICData::New(Function::Handle(), | 2294 value_check = ICData::New(flow_graph_->parsed_function().function(), |
| 2300 Object::null_string(), | 2295 call->function_name(), |
| 2301 Object::null_array(), // Dummy args. descr. | 2296 Object::empty_array(), // Dummy args. descr. |
| 2302 Isolate::kNoDeoptId, | 2297 Isolate::kNoDeoptId, |
| 2303 1); | 2298 1); |
| 2304 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | 2299 value_check.AddReceiverCheck(kSmiCid, target); |
| 2305 } | 2300 } |
| 2306 break; | 2301 break; |
| 2307 case kTypedDataFloat32ArrayCid: | 2302 case kTypedDataFloat32ArrayCid: |
| 2308 case kTypedDataFloat64ArrayCid: { | 2303 case kTypedDataFloat64ArrayCid: { |
| 2309 // Check that value is always double. | 2304 // Check that value is always double. |
| 2310 value_check = ICData::New(Function::Handle(), | 2305 value_check = ICData::New(flow_graph_->parsed_function().function(), |
| 2311 Object::null_string(), | 2306 call->function_name(), |
| 2312 Object::null_array(), // Dummy args. descr. | 2307 Object::empty_array(), // Dummy args. descr. |
| 2313 Isolate::kNoDeoptId, | 2308 Isolate::kNoDeoptId, |
| 2314 1); | 2309 1); |
| 2315 value_check.AddReceiverCheck(kDoubleCid, Function::Handle()); | 2310 value_check.AddReceiverCheck(kDoubleCid, target); |
| 2316 break; | 2311 break; |
| 2317 } | 2312 } |
| 2318 case kTypedDataFloat32x4ArrayCid: { | 2313 case kTypedDataFloat32x4ArrayCid: { |
| 2319 // Check that value is always Float32x4. | 2314 // Check that value is always Float32x4. |
| 2320 value_check = ICData::New(Function::Handle(), | 2315 value_check = ICData::New(flow_graph_->parsed_function().function(), |
| 2321 Object::null_string(), | 2316 call->function_name(), |
| 2322 Object::null_array(), // Dummy args. descr. | 2317 Object::empty_array(), // Dummy args. descr. |
| 2323 Isolate::kNoDeoptId, | 2318 Isolate::kNoDeoptId, |
| 2324 1); | 2319 1); |
| 2325 value_check.AddReceiverCheck(kFloat32x4Cid, Function::Handle()); | 2320 value_check.AddReceiverCheck(kFloat32x4Cid, target); |
| 2326 break; | 2321 break; |
| 2327 } | 2322 } |
| 2328 default: | 2323 default: |
| 2329 // Array cids are already checked in the caller. | 2324 // Array cids are already checked in the caller. |
| 2330 UNREACHABLE(); | 2325 UNREACHABLE(); |
| 2331 } | 2326 } |
| 2332 | 2327 |
| 2333 Definition* index = call->ArgumentAt(1); | 2328 Definition* index = call->ArgumentAt(1); |
| 2334 Definition* stored_value = call->ArgumentAt(2); | 2329 Definition* stored_value = call->ArgumentAt(2); |
| 2335 if (!value_check.IsNull()) { | 2330 if (!value_check.IsNull()) { |
| (...skipping 5007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7343 | 7338 |
| 7344 // Insert materializations at environment uses. | 7339 // Insert materializations at environment uses. |
| 7345 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 7340 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
| 7346 for (intptr_t i = 0; i < exits.length(); i++) { | 7341 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7347 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 7342 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
| 7348 } | 7343 } |
| 7349 } | 7344 } |
| 7350 | 7345 |
| 7351 | 7346 |
| 7352 } // namespace dart | 7347 } // namespace dart |
| OLD | NEW |