| OLD | NEW | 
| (Empty) |  | 
 |   1 // Copyright 2015 the V8 project authors. All rights reserved. | 
 |   2 // Use of this source code is governed by a BSD-style license that can be | 
 |   3 // found in the LICENSE file. | 
 |   4  | 
 |   5 // Flags: --allow-natives-syntax --expose-gc --block-concurrent-recompilation | 
 |   6  | 
 |   7 function Inner() { | 
 |   8   this.property = "OK"; | 
 |   9   this.prop2 = 1; | 
 |  10 } | 
 |  11  | 
 |  12 function Outer() { | 
 |  13   this.o = "u"; | 
 |  14 } | 
 |  15 function KeepMapAlive(o) { | 
 |  16   return o.o; | 
 |  17 } | 
 |  18 function SetInner(o, i) { | 
 |  19   o.inner_field = i; | 
 |  20 } | 
 |  21 function Crash(o) { | 
 |  22   return o.inner_field.property; | 
 |  23 } | 
 |  24  | 
 |  25 var inner = new Inner(); | 
 |  26 var outer = new Outer(); | 
 |  27  | 
 |  28 // Collect type feedback. | 
 |  29 SetInner(new Outer(), inner); | 
 |  30 SetInner(outer, inner); | 
 |  31  | 
 |  32 // This function's only purpose is to stash away a Handle that keeps | 
 |  33 // outer's map alive during the gc() call below. We store this handle | 
 |  34 // on the compiler thread :-) | 
 |  35 KeepMapAlive(outer); | 
 |  36 KeepMapAlive(outer); | 
 |  37 %OptimizeFunctionOnNextCall(KeepMapAlive, "concurrent"); | 
 |  38 KeepMapAlive(outer); | 
 |  39  | 
 |  40 // So far, all is well. Collect type feedback and optimize. | 
 |  41 print(Crash(outer)); | 
 |  42 print(Crash(outer)); | 
 |  43 %OptimizeFunctionOnNextCall(Crash); | 
 |  44 print(Crash(outer)); | 
 |  45  | 
 |  46 // Null out references and perform GC. This will keep outer's map alive | 
 |  47 // (due to the handle created above), but will let inner's map die. Hence, | 
 |  48 // inner_field's field type stored in outer's map will get cleared. | 
 |  49 inner = undefined; | 
 |  50 outer = undefined; | 
 |  51 gc(); | 
 |  52  | 
 |  53 // We could unblock the compiler thread now. But why bother? | 
 |  54  | 
 |  55 // Now optimize SetInner while inner_field's type is still cleared! | 
 |  56 // This will generate optimized code that stores arbitrary objects | 
 |  57 // into inner_field without checking their type against the field type. | 
 |  58 %OptimizeFunctionOnNextCall(SetInner); | 
 |  59  | 
 |  60 // Use the optimized code to store an arbitrary object into | 
 |  61 // o2's inner_field, without triggering any dependent code deopts... | 
 |  62 var o2 = new Outer(); | 
 |  63 SetInner(o2, { invalid: 1.51, property: "OK" }); | 
 |  64 // ...and then use the existing code expecting an Inner-class object to | 
 |  65 // read invalid data (in this case, a raw double). | 
 |  66 // We crash trying to convert the raw double into a printable string. | 
 |  67 print(Crash(o2)); | 
| OLD | NEW |