b6643320b9
In order to reduce the codegen size of dynamic map checks, add the ability to have an eager with resume deopt point, which can call a given builitin to perform a more detailed check than can be done in codegen, and then either deoptimizes itself (as if the calling code had performed an eager deopt) or resumes execution in the calling code after the check. In addition, support for adding extra arguments to a deoptimization continuation is added to enable us to pass the necessary arguments to the DynamicMapChecks builtin. Finally, a trampoline is added to the DynamicMapChecks which saves the registers that might be clobbered by that builtin, to avoid having to save them in the generated code. This trampoline also performs the deoptimization based on the result of the DynamicMapChecks builtin. In order to ensure both the trampoline and DynamicMapChecks builtin have the same call interface, and to limit the number of registers that need saving in the trampoline, the DynamicMapChecks builtin is moved to be a CSA builtin with a custom CallInterfaceDescriptor, that calls an exported Torque macro that implements the actual functionality. All told, this changes the codegen for a monomorphic dynamic map check from: movl rbx,<expected_map> cmpl [<object>-0x1],rbx jnz <deferred_call> resume_point: ... deferred_call: <spill registers> movl rax,<slot> movq rbx,<object> movq rcx,<handler> movq r10,<DynamicMapChecks> call r10 cmpq rax,0x0 jz <restore_regs> cmpq rax,0x1 jz <deopt_point_1> cmpq rax,0x2 jz <deopt_point_2> int3l restore_regs: <restore_regs> jmp <resume_point> ... deopt_point_1: call Deoptimization_Eager deopt_point_2: call Deoptimization_Bailout To: movl rax,<slot> movl rcx,<expected_map> movq rdx,<handler> cmpl [<object>-0x1],rcx jnz <deopt_point> resume_point: ... deopt_point: call DynamicMapChecksTrampoline jmp <resume_point> BUG=v8:10582 Change-Id: Ica4927b9acc963b9b73dc62d9379a7815335650f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2560197 Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#71545}
47 lines
1.2 KiB
JavaScript
47 lines
1.2 KiB
JavaScript
// Copyright 2020 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 --turboprop --turbo-dynamic-map-checks
|
|
// Flags: --opt --no-always-opt --deopt-every-n-times=0
|
|
|
|
function b(a) { return a; }
|
|
|
|
function f(o, should_bailout) {
|
|
b(o.a);
|
|
let did_bailout = (%GetOptimizationStatus(f) &
|
|
V8OptimizationStatus.kTopmostFrameIsTurboFanned) == 0;
|
|
assertEquals(should_bailout, did_bailout);
|
|
}
|
|
|
|
var o = {a:10, b:20, c:30};
|
|
var o1 = {a:10, b:20, c:30};
|
|
var o2 = {a:10, b:20, c:30};
|
|
%PrepareFunctionForOptimization(f);
|
|
f(o, true);
|
|
%OptimizeFunctionOnNextCall(f);
|
|
f(o, false);
|
|
assertOptimized(f);
|
|
|
|
// Transition o to a new map and deprecate the old one (which is embedded in the
|
|
// optimized code for the dynamic map check).
|
|
o.b = 10.23;
|
|
f(o, true);
|
|
f(o1, false);
|
|
f(o2, false);
|
|
assertOptimized(f);
|
|
|
|
// Deprecate o's new map again and update the feedback vector but don't migrate
|
|
// o.
|
|
o1.c = 20.23;
|
|
f(o1, true);
|
|
assertOptimized(f);
|
|
|
|
// We should migrates o's map with a bailout, but then should not bailout after
|
|
// migrating.
|
|
f(o, true);
|
|
f(o, false);
|
|
f(o1, false);
|
|
f(o2, false);
|
|
assertOptimized(f);
|