v8/test/cctest/compiler/serializer-tester.cc
Maya Lekova 7b69507ca6 [turbofan] Add handling of jumps to the serializer
Implemented branching and merging of Environments to facilitate handling of
conditional and unconditional jumps in the SerializerForBackgroundCompilation.
Added tests and printing helpers for the Environment. The internal structure
of the hints was changed to ZoneSet to support avoiding of duplicates.
Alternative implementation considerations were documented here:
https://docs.google.com/document/d/1vCQYhtFPqXafSMweSnGD8l0TKEIB6cPV5UGMHJtpy8k/edit?ts=5bf7d341#heading=h.jx4br0df5qzm

R=neis@chromium.org

Bug: v8:7790
Change-Id: Ib929c75ddb7f7fb290a5ca28d4422680a1514a4f
Reviewed-on: https://chromium-review.googlesource.com/c/1451847
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59534}
2019-02-12 14:36:18 +00:00

220 lines
6.4 KiB
C++

// Copyright 2019 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.
// Serializer tests don't make sense in lite mode, as it doesn't gather
// IC feedback.
#ifndef V8_LITE_MODE
#include "test/cctest/compiler/serializer-tester.h"
#include "src/api-inl.h"
#include "src/compiler/serializer-for-background-compilation.h"
#include "src/compiler/zone-stats.h"
#include "src/optimized-compilation-info.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
namespace compiler {
SerializerTester::SerializerTester(const char* source)
: canonical_(main_isolate()) {
// The tests only make sense in the context of concurrent compilation.
FLAG_concurrent_inlining = true;
// The tests don't make sense when optimizations are turned off.
FLAG_opt = true;
// We need the IC to feed it to the serializer.
FLAG_use_ic = true;
// We need manual control over when a given function is optimized.
FLAG_always_opt = false;
// We need allocation of executable memory for the compilation.
FLAG_jitless = false;
std::string function_string = "(function() { ";
function_string += source;
function_string += " })();";
Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CompileRun(function_string.c_str()))));
uint32_t flags = i::OptimizedCompilationInfo::kInliningEnabled |
i::OptimizedCompilationInfo::kFunctionContextSpecializing |
i::OptimizedCompilationInfo::kAccessorInliningEnabled |
i::OptimizedCompilationInfo::kLoopPeelingEnabled |
i::OptimizedCompilationInfo::kBailoutOnUninitialized |
i::OptimizedCompilationInfo::kAllocationFoldingEnabled |
i::OptimizedCompilationInfo::kSplittingEnabled |
i::OptimizedCompilationInfo::kAnalyzeEnvironmentLiveness;
Optimize(function, main_zone(), main_isolate(), flags, &broker_);
function_ = JSFunctionRef(broker_, function);
}
TEST(SerializeEmptyFunction) {
SerializerTester tester("function f() {}; return f;");
CHECK(tester.function().IsSerializedForCompilation());
}
// This helper function allows for testing weather an inlinee candidate
// was properly serialized. It expects that the top-level function (that is
// run through the SerializerTester) will return its inlinee candidate.
void CheckForSerializedInlinee(const char* source, int argc = 0,
Handle<Object> argv[] = {}) {
SerializerTester tester(source);
JSFunctionRef f = tester.function();
CHECK(f.IsSerializedForCompilation());
MaybeHandle<Object> g_obj = Execution::Call(
tester.isolate(), tester.function().object(),
tester.isolate()->factory()->undefined_value(), argc, argv);
Handle<Object> g;
CHECK(g_obj.ToHandle(&g));
Handle<JSFunction> g_func = Handle<JSFunction>::cast(g);
SharedFunctionInfoRef g_sfi(tester.broker(),
handle(g_func->shared(), tester.isolate()));
FeedbackVectorRef g_fv(tester.broker(),
handle(g_func->feedback_vector(), tester.isolate()));
CHECK(g_sfi.IsSerializedForCompilation(g_fv));
}
TEST(SerializeInlinedClosure) {
CheckForSerializedInlinee(
"function f() {"
" return (function g(){ return g; })();"
"}; f(); return f;");
}
TEST(SerializeInlinedFunction) {
CheckForSerializedInlinee(
"function g() {};"
"function f() {"
" g(); return g;"
"}; f(); return f;");
}
TEST(SerializeCallUndefinedReceiver) {
CheckForSerializedInlinee(
"function g(a,b,c) {};"
"function f() {"
" g(1,2,3); return g;"
"}; f(); return f;");
}
TEST(SerializeCallUndefinedReceiver2) {
CheckForSerializedInlinee(
"function g(a,b) {};"
"function f() {"
" g(1,2); return g;"
"}; f(); return f;");
}
TEST(SerializeCallProperty) {
CheckForSerializedInlinee(
"let obj = {"
" g: function g(a,b,c) {}"
"};"
"function f() {"
" obj.g(1,2,3); return obj.g;"
"}; f(); return f;");
}
TEST(SerializeCallProperty2) {
CheckForSerializedInlinee(
"let obj = {"
" g: function g(a,b) {}"
"};"
"function f() {"
" obj.g(1,2); return obj.g;"
"}; f(); return f;");
}
TEST(SerializeCallAnyReceiver) {
CheckForSerializedInlinee(
"let obj = {"
" g: function g() {}"
"};"
"function f() {"
" with(obj) {"
" g(); return g;"
" };"
"};"
"f(); return f;");
}
TEST(SerializeCallWithSpread) {
CheckForSerializedInlinee(
"function g(args) {};"
"const arr = [1,2,3];"
"function f() {"
" g(...arr); return g;"
"}; f(); return f;");
}
// The following test causes the CallIC of `g` to turn megamorphic,
// thus allowing us to test if we forward arguments hints (`callee` in this
// example) and correctly serialize the inlining candidate `j`.
TEST(SerializeCallArguments) {
CheckForSerializedInlinee(
"function g(callee) { callee(); };"
"function h() {};"
"function i() {};"
"g(h); g(i);"
"function f() {"
" function j() {};"
" g(j);"
" return j;"
"}; f(); return f;");
}
TEST(SerializeConstruct) {
CheckForSerializedInlinee(
"function g() {};"
"function f() {"
" new g(); return g;"
"}; f(); return f;");
}
TEST(SerializeConstructWithSpread) {
CheckForSerializedInlinee(
"function g(a, b, c) {};"
"const arr = [1, 2];"
"function f() {"
" new g(0, ...arr); return g;"
"}; f(); return f;");
}
TEST(SerializeConditionalJump) {
CheckForSerializedInlinee(
"function g(callee) { callee(); };"
"function h() {};"
"function i() {};"
"let a = true;"
"g(h); g(i);"
"function f() {"
" function q() {};"
" if (a) g(q);"
" return q;"
"}; f(); return f;");
}
TEST(SerializeUnconditionalJump) {
CheckForSerializedInlinee(
"function g(callee) { callee(); };"
"function h() {};"
"function i() {};"
"let a = false;"
"g(h); g(i);"
"function f() {"
" function p() {};"
" function q() {};"
" if (a) g(q);"
" else g(p);"
" return p;"
"}; f(); return f;");
}
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_LITE_MODE