Commit 25895aee authored by Benedikt Meurer's avatar Benedikt Meurer

[turbofan] Add support for inlining of builtins.

We mark certain builtins for inlining, and those should always be
inlined into optimized code (CrankShaft already handles it this way), so
we should support that in TurboFan as well. Currently this mainly
affects a certain set of Math functions, but once have the basics in
place we can extend this to any kind of builtin/code stub/accessor.

This adds a new flag --turbo_builtin_inlining (enabled by default), that
forces the inliner to always inline builtins marked for inlining, but
does not affect inlining of other functions (this is still controlled by
the --turbo-inlining flag).

BUG=v8:3952
LOG=n
R=jarin@chromium.org

Review URL: https://codereview.chromium.org/993473002

Cr-Commit-Position: refs/heads/master@{#27059}
parent 4b6afb84
......@@ -187,6 +187,7 @@ void CompilationInfo::Initialize(Isolate* isolate,
if (isolate_->debug()->is_active()) MarkAsDebug();
if (FLAG_context_specialization) MarkAsContextSpecializing();
if (FLAG_turbo_builtin_inlining) MarkAsBuiltinInliningEnabled();
if (FLAG_turbo_inlining) MarkAsInliningEnabled();
if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
if (FLAG_turbo_types) MarkAsTypingEnabled();
......
......@@ -167,7 +167,8 @@ class CompilationInfo {
kDisableFutureOptimization = 1 << 20,
kModule = 1 << 21,
kToplevel = 1 << 22,
kSplittingEnabled = 1 << 23
kSplittingEnabled = 1 << 23,
kBuiltinInliningEnabled = 1 << 24
};
CompilationInfo(Handle<JSFunction> closure, Zone* zone);
......@@ -294,6 +295,12 @@ class CompilationInfo {
bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
void MarkAsBuiltinInliningEnabled() { SetFlag(kBuiltinInliningEnabled); }
bool is_builtin_inlining_enabled() const {
return GetFlag(kBuiltinInliningEnabled);
}
void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
......
......@@ -328,6 +328,10 @@ Reduction JSInliner::Reduce(Node* node) {
if (!match.HasValue()) return NoChange();
Handle<JSFunction> function = match.Value().handle();
if (!function->IsJSFunction()) return NoChange();
if (mode_ == kBuiltinsInlining && !function->shared()->inline_builtin()) {
return NoChange();
}
CompilationInfoWithZone info(function);
......
......@@ -16,12 +16,16 @@ class JSCallFunctionAccessor;
class JSInliner FINAL : public Reducer {
public:
JSInliner(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph)
: local_zone_(local_zone), info_(info), jsgraph_(jsgraph) {}
enum Mode { kBuiltinsInlining, kGeneralInlining };
JSInliner(Mode mode, Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph)
: mode_(mode), local_zone_(local_zone), info_(info), jsgraph_(jsgraph) {}
Reduction Reduce(Node* node) FINAL;
private:
Mode const mode_;
Zone* local_zone_;
CompilationInfo* info_;
JSGraph* jsgraph_;
......
......@@ -450,7 +450,10 @@ struct InliningPhase {
void Run(PipelineData* data, Zone* temp_zone) {
SourcePositionTable::Scope pos(data->source_positions(),
SourcePosition::Unknown());
JSInliner inliner(temp_zone, data->info(), data->jsgraph());
JSInliner inliner(data->info()->is_inlining_enabled()
? JSInliner::kGeneralInlining
: JSInliner::kBuiltinsInlining,
temp_zone, data->info(), data->jsgraph());
GraphReducer graph_reducer(data->graph(), temp_zone);
AddReducer(data, &graph_reducer, &inliner);
graph_reducer.ReduceGraph();
......@@ -915,7 +918,7 @@ Handle<Code> Pipeline::GenerateCode() {
RunPrintAndVerify("Context specialized", true);
}
if (info()->is_inlining_enabled()) {
if (info()->is_builtin_inlining_enabled() || info()->is_inlining_enabled()) {
Run<InliningPhase>();
RunPrintAndVerify("Inlined", true);
}
......
......@@ -408,9 +408,11 @@ DEFINE_BOOL(context_specialization, false,
"enable context specialization in TurboFan")
DEFINE_BOOL(turbo_deoptimization, false, "enable deoptimization in TurboFan")
DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan")
DEFINE_BOOL(turbo_builtin_inlining, true, "enable builtin inlining in TurboFan")
DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
DEFINE_BOOL(loop_assignment_analysis, true, "perform loop assignment analysis")
DEFINE_IMPLICATION(turbo_inlining, turbo_types)
DEFINE_IMPLICATION(turbo_builtin_inlining, turbo_types)
DEFINE_BOOL(turbo_profiling, false, "enable profiling in TurboFan")
// TODO(dcarney): this is just for experimentation, remove when default.
DEFINE_BOOL(turbo_delay_ssa_decon, false,
......
......@@ -34,6 +34,7 @@ class FunctionTester : public InitializedHandleScope {
flags_(flags) {
Compile(function);
const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
CompilationInfo::kBuiltinInliningEnabled |
CompilationInfo::kInliningEnabled |
CompilationInfo::kTypingEnabled;
CHECK_EQ(0u, flags_ & ~supported_flags);
......
......@@ -11,9 +11,11 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
namespace {
// Helper to determine inline count via JavaScriptFrame::GetInlineCount.
// Note that a count of 1 indicates that no inlining has occured.
static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
StackTraceFrameIterator it(CcTest::i_isolate());
int frames_seen = 0;
JavaScriptFrame* topmost = it.frame();
......@@ -30,7 +32,7 @@ static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
}
static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::FunctionTemplate> t =
v8::FunctionTemplate::New(isolate, AssertInlineCount);
......@@ -38,9 +40,15 @@ static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
}
static uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
CompilationInfo::kContextSpecializing |
CompilationInfo::kTypingEnabled;
const uint32_t kBuiltinInlineFlags = CompilationInfo::kBuiltinInliningEnabled |
CompilationInfo::kContextSpecializing |
CompilationInfo::kTypingEnabled;
const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
CompilationInfo::kContextSpecializing |
CompilationInfo::kTypingEnabled;
} // namespace
TEST(SimpleInlining) {
......@@ -484,4 +492,20 @@ TEST(InlineWithArguments) {
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
TEST(InlineBuiltin) {
FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s,t,u) { AssertInlineCount(2); return true; }"
" function bar() { return foo(); };"
" %SetInlineBuiltinFlag(foo);"
" return bar;"
"})();",
kBuiltinInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value());
}
#endif // V8_TURBOFAN_TARGET
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment