|  | // Copyright 2018 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Flags: --allow-natives-syntax --opt --noalways-opt --stress-flush-bytecode | 
|  | // Flags: --expose-gc | 
|  |  | 
|  | Debug = debug.Debug | 
|  |  | 
|  | function foo() { | 
|  | return 44; | 
|  | } | 
|  |  | 
|  | function listener(event, exec_state, event_data, data) { | 
|  | if (event != Debug.DebugEvent.Break) return; | 
|  |  | 
|  | // Optimize foo. | 
|  | %PrepareFunctionForOptimization(foo); | 
|  | %OptimizeFunctionOnNextCall(foo); | 
|  | foo(); | 
|  | assertOptimized(foo); | 
|  |  | 
|  | // Lazily deopt foo, which marks the code for deoptimization and invalidates | 
|  | // the DeoptimizationData, but doesn't unlink the optimized code entry in | 
|  | // foo's JSFunction. | 
|  | %DeoptimizeFunction(foo); | 
|  |  | 
|  | // Run the GC. Since the DeoptimizationData is now dead, the bytecode | 
|  | // associated with the optimized code is free to be flushed, which also | 
|  | // free's the feedback vector meta-data. | 
|  | gc(); | 
|  |  | 
|  | // Execute foo with side-effect checks, which causes the debugger to call | 
|  | // DeoptimizeFunction on foo. Even though the code is already marked for | 
|  | // deoptimization, this will try to unlink the optimized code from the | 
|  | // feedback vector, which will fail due to the feedback meta-data being | 
|  | // flushed. The deoptimizer should call JSFunction::ResetIfBytecodeFlushed | 
|  | // before trying to do this, which will clear the whole feedback vector and | 
|  | // reset the JSFunction's code entry field to CompileLazy. | 
|  | exec_state.frame(0).evaluate("foo()", true); | 
|  | } | 
|  |  | 
|  | // Add the debug event listener. | 
|  | Debug.setListener(listener); | 
|  |  | 
|  | function f() { | 
|  | debugger; | 
|  | } | 
|  | f(); |