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

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

Issue 10942006: Fix bad optimization of instance-of with uninstantiated types (issue 5216). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
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 4
5 #include "vm/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 ForwardInstructionIterator it(entry); 284 ForwardInstructionIterator it(entry);
285 current_iterator_ = ⁢ 285 current_iterator_ = ⁢
286 for (; !it.Done(); it.Advance()) { 286 for (; !it.Done(); it.Advance()) {
287 it.Current()->Accept(this); 287 it.Current()->Accept(this);
288 } 288 }
289 current_iterator_ = NULL; 289 current_iterator_ = NULL;
290 } 290 }
291 } 291 }
292 292
293 293
294 // Returns true if the compile type of this value is more specific than the
295 // given dst_type.
296 // TODO(regis): Support a set of compile types for the given value. 294 // TODO(regis): Support a set of compile types for the given value.
297 bool Value::CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const { 295 bool Value::CanComputeIsNull(bool* is_null) const {
298 // No type is more specific than a malformed type. 296 // For now, we can only return a meaningful result if the value is constant.
299 if (dst_type.IsMalformed()) { 297 if (!BindsToConstant()) {
300 return false; 298 return false;
301 } 299 }
302 300
303 // If the value is the null constant, its type (NullType) is more specific 301 // Return true if the constant value is Object::null.
304 // than the destination type, even if the destination type is the void type,
305 // since a void function is allowed to return null.
306 if (BindsToConstantNull()) { 302 if (BindsToConstantNull()) {
303 *is_null = true;
307 return true; 304 return true;
308 } 305 }
309 306
310 // Functions that do not explicitly return a value, implicitly return null, 307 // Consider the compile type of the value to check for sentinels, which are
311 // except generative constructors, which return the object being constructed. 308 // also treated as null.
312 // It is therefore acceptable for void functions to return null. 309 const AbstractType& compile_type = AbstractType::Handle(CompileType());
313 // In case of a null constant, we have already returned true above, else we 310 ASSERT(!compile_type.IsMalformed());
314 // return false here. 311 ASSERT(!compile_type.IsVoidType());
315 if (dst_type.IsVoidType()) { 312
313 // There are only three instances that can be of type Null:
314 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
315 // The inline code and run time code performing the type check will only
316 // encounter the 2 sentinel values if type check elimination was disabled.
317 // Otherwise, the type check of a sentinel value will be eliminated here,
318 // because these sentinel values can only be encountered as constants, never
319 // as actual value of a heap object being type checked.
320 if (compile_type.IsNullType()) {
321 *is_null = true;
322 return true;
323 }
324
325 return false;
326 }
327
328
329 // TODO(regis): Support a set of compile types for the given value.
330 bool Value::CanComputeIsInstanceOf(const AbstractType& type,
331 bool* is_instance) const {
332 // We cannot give an answer if the given type is malformed.
333 if (type.IsMalformed()) {
316 return false; 334 return false;
317 } 335 }
318 336
337 // We should never test for an instance of null.
338 ASSERT(!type.IsNullType());
339
319 // Consider the compile type of the value. 340 // Consider the compile type of the value.
320 const AbstractType& compile_type = AbstractType::Handle(CompileType()); 341 const AbstractType& compile_type = AbstractType::Handle(CompileType());
321 ASSERT(!compile_type.IsMalformed()); 342 ASSERT(!compile_type.IsMalformed());
322 343
323 // If the compile type of the value is void, we are type checking the result 344 // If the compile type of the value is void, we are type checking the result
324 // of a void function, which was checked to be null at the return statement 345 // of a void function, which was checked to be null at the return statement
325 // inside the function. 346 // inside the function.
326 if (compile_type.IsVoidType()) { 347 if (compile_type.IsVoidType()) {
348 ASSERT(FLAG_enable_type_checks);
327 return true; 349 return true;
zerny-google 2012/09/18 11:20:24 is_instance does not appear to be set when this re
regis 2012/09/18 14:55:44 Good catch!
328 } 350 }
329 351
330 // If the compile type of the value is NullType, the type test is eliminated. 352 // The Null type is only a subtype of Object and of Dynamic.
331 // There are only three instances that can be of Class Null: 353 // Functions that do not explicitly return a value, implicitly return null,
332 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). 354 // except generative constructors, which return the object being constructed.
333 // The inline code and run time code performing the type check will never 355 // It is therefore acceptable for void functions to return null.
334 // encounter the 2 sentinel values. The type check of a sentinel value
335 // will always be eliminated here, because these sentinel values can only
336 // be encountered as constants, never as actual value of a heap object
337 // being type checked.
338 if (compile_type.IsNullType()) { 356 if (compile_type.IsNullType()) {
357 *is_instance =
358 type.IsObjectType() || type.IsDynamicType() || type.IsVoidType();
339 return true; 359 return true;
340 } 360 }
341 361
362 // Until we support a set of compile types, we can only give answers for
363 // constant values. Indeed, a variable of the proper compile time type may
364 // still hold null at run time and therefore fail the test.
365 if (!BindsToConstant()) {
366 return false;
367 }
368
369 // A non-null constant is not an instance of void.
370 if (type.IsVoidType()) {
371 *is_instance = false;
372 return true;
373 }
374
375 // Since the value is a constant, its type is instantiated.
376 ASSERT(compile_type.IsInstantiated());
377
342 // The run time type of the value is guaranteed to be a subtype of the 378 // The run time type of the value is guaranteed to be a subtype of the
343 // compile time type of the value. However, establishing here that 379 // compile time type of the value. However, establishing here that the
344 // the compile time type is a subtype of the destination type does not 380 // compile time type is a subtype of the given type does not guarantee that
345 // guarantee that the run time type will also be a subtype of the destination 381 // the run time type will also be a subtype of the given type, because the
346 // type, because the subtype relation is not transitive. 382 // subtype relation is not transitive when an uninstantiated type is
347 // However, the 'more specific than' relation is transitive and is used 383 // involved.
348 // here. In other words, if the compile type of the value is more specific 384 Error& malformed_error = Error::Handle();
349 // than the destination type, the run time type of the value, which is 385 if (type.IsInstantiated()) {
350 // guaranteed to be a subtype of the compile type, is also guaranteed to be 386 // Perform the test on the compile-time type and provide the answer, unless
351 // a subtype of the destination type and the type check can therefore be 387 // the type test produced a malformed error (e.g. an upper bound error).
352 // eliminated. 388 *is_instance = compile_type.IsSubtypeOf(type, &malformed_error);
353 return compile_type.IsMoreSpecificThan(dst_type, NULL); 389 } else {
390 // However, the 'more specific than' relation is transitive and used here.
391 // In other words, if the compile type of the value is more specific than
392 // the given type, the run time type of the value, which is guaranteed to be
393 // a subtype of the compile type, is also guaranteed to be a subtype of the
394 // given type.
395 *is_instance = compile_type.IsMoreSpecificThan(type, &malformed_error);
396 }
397 return malformed_error.IsNull();
354 } 398 }
355 399
356 400
357 bool Value::NeedsStoreBuffer() const { 401 bool Value::NeedsStoreBuffer() const {
358 const intptr_t cid = ResultCid(); 402 const intptr_t cid = ResultCid();
359 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { 403 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) {
360 return false; 404 return false;
361 } 405 }
362 return !BindsToConstant(); 406 return !BindsToConstant();
363 } 407 }
(...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 value->set_use_index(use_index++); 1736 value->set_use_index(use_index++);
1693 value->AddToEnvUseList(); 1737 value->AddToEnvUseList();
1694 } 1738 }
1695 instr->set_env(copy); 1739 instr->set_env(copy);
1696 } 1740 }
1697 1741
1698 1742
1699 #undef __ 1743 #undef __
1700 1744
1701 } // namespace dart 1745 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/object.cc » ('j') | runtime/vm/object.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698