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

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
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 ASSERT(is_null != NULL);
299 if (dst_type.IsMalformed()) { 297 // For now, we can only return a meaningful result if the value is constant.
298 if (!BindsToConstant()) {
300 return false; 299 return false;
301 } 300 }
302 301
303 // If the value is the null constant, its type (NullType) is more specific 302 // 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()) { 303 if (BindsToConstantNull()) {
304 *is_null = true;
307 return true; 305 return true;
308 } 306 }
309 307
310 // Functions that do not explicitly return a value, implicitly return null, 308 // Consider the compile type of the value to check for sentinels, which are
311 // except generative constructors, which return the object being constructed. 309 // also treated as null.
312 // It is therefore acceptable for void functions to return null. 310 const AbstractType& compile_type = AbstractType::Handle(CompileType());
313 // In case of a null constant, we have already returned true above, else we 311 ASSERT(!compile_type.IsMalformed());
314 // return false here. 312 ASSERT(!compile_type.IsVoidType());
315 if (dst_type.IsVoidType()) { 313
314 // There are only three instances that can be of type Null:
315 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
316 // The inline code and run time code performing the type check will only
317 // encounter the 2 sentinel values if type check elimination was disabled.
318 // Otherwise, the type check of a sentinel value will be eliminated here,
319 // because these sentinel values can only be encountered as constants, never
320 // as actual value of a heap object being type checked.
321 if (compile_type.IsNullType()) {
322 *is_null = true;
323 return true;
324 }
325
326 return false;
327 }
328
329
330 // TODO(regis): Support a set of compile types for the given value.
331 bool Value::CanComputeIsInstanceOf(const AbstractType& type,
332 bool* is_instance) const {
333 ASSERT(is_instance != NULL);
334 // We cannot give an answer if the given type is malformed.
335 if (type.IsMalformed()) {
316 return false; 336 return false;
317 } 337 }
318 338
339 // We should never test for an instance of null.
340 ASSERT(!type.IsNullType());
341
319 // Consider the compile type of the value. 342 // Consider the compile type of the value.
320 const AbstractType& compile_type = AbstractType::Handle(CompileType()); 343 const AbstractType& compile_type = AbstractType::Handle(CompileType());
321 ASSERT(!compile_type.IsMalformed()); 344 ASSERT(!compile_type.IsMalformed());
322 345
323 // If the compile type of the value is void, we are type checking the result 346 // 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 347 // of a void function, which was checked to be null at the return statement
325 // inside the function. 348 // inside the function.
326 if (compile_type.IsVoidType()) { 349 if (compile_type.IsVoidType()) {
350 ASSERT(FLAG_enable_type_checks);
351 *is_instance = true;
327 return true; 352 return true;
328 } 353 }
329 354
330 // If the compile type of the value is NullType, the type test is eliminated. 355 // The Null type is only a subtype of Object and of Dynamic.
331 // There are only three instances that can be of Class Null: 356 // Functions that do not explicitly return a value, implicitly return null,
332 // Object::null(), Object::sentinel(), and Object::transition_sentinel(). 357 // except generative constructors, which return the object being constructed.
333 // The inline code and run time code performing the type check will never 358 // 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()) { 359 if (compile_type.IsNullType()) {
360 *is_instance =
361 type.IsObjectType() || type.IsDynamicType() || type.IsVoidType();
339 return true; 362 return true;
340 } 363 }
341 364
365 // Until we support a set of compile types, we can only give answers for
366 // constant values. Indeed, a variable of the proper compile time type may
367 // still hold null at run time and therefore fail the test.
368 if (!BindsToConstant()) {
369 return false;
370 }
371
372 // A non-null constant is not an instance of void.
373 if (type.IsVoidType()) {
374 *is_instance = false;
375 return true;
376 }
377
378 // Since the value is a constant, its type is instantiated.
379 ASSERT(compile_type.IsInstantiated());
380
342 // The run time type of the value is guaranteed to be a subtype of the 381 // 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 382 // 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 383 // 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 384 // the run time type will also be a subtype of the given type, because the
346 // type, because the subtype relation is not transitive. 385 // subtype relation is not transitive when an uninstantiated type is
347 // However, the 'more specific than' relation is transitive and is used 386 // involved.
348 // here. In other words, if the compile type of the value is more specific 387 Error& malformed_error = Error::Handle();
349 // than the destination type, the run time type of the value, which is 388 if (type.IsInstantiated()) {
350 // guaranteed to be a subtype of the compile type, is also guaranteed to be 389 // 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 390 // the type test produced a malformed error (e.g. an upper bound error).
352 // eliminated. 391 *is_instance = compile_type.IsSubtypeOf(type, &malformed_error);
353 return compile_type.IsMoreSpecificThan(dst_type, NULL); 392 } else {
393 // However, the 'more specific than' relation is transitive and used here.
394 // In other words, if the compile type of the value is more specific than
395 // the given type, the run time type of the value, which is guaranteed to be
396 // a subtype of the compile type, is also guaranteed to be a subtype of the
397 // given type.
398 *is_instance = compile_type.IsMoreSpecificThan(type, &malformed_error);
399 }
400 return malformed_error.IsNull();
354 } 401 }
355 402
356 403
357 bool Value::NeedsStoreBuffer() const { 404 bool Value::NeedsStoreBuffer() const {
358 const intptr_t cid = ResultCid(); 405 const intptr_t cid = ResultCid();
359 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) { 406 if ((cid == kSmiCid) || (cid == kBoolCid) || (cid == kNullCid)) {
360 return false; 407 return false;
361 } 408 }
362 return !BindsToConstant(); 409 return !BindsToConstant();
363 } 410 }
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after
1707 value->set_use_index(use_index++); 1754 value->set_use_index(use_index++);
1708 value->AddToEnvUseList(); 1755 value->AddToEnvUseList();
1709 } 1756 }
1710 instr->env()->outer_ = copy; 1757 instr->env()->outer_ = copy;
1711 } 1758 }
1712 1759
1713 1760
1714 #undef __ 1761 #undef __
1715 1762
1716 } // namespace dart 1763 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698