"src/compiler/js-builtin-reducer.h",
"src/compiler/js-context-specialization.cc",
"src/compiler/js-context-specialization.h",
+ "src/compiler/js-frame-specialization.cc",
+ "src/compiler/js-frame-specialization.h",
"src/compiler/js-generic-lowering.cc",
"src/compiler/js-generic-lowering.h",
"src/compiler/js-graph.cc",
}
if (info()->shared_info()->asm_function()) {
+ if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
info()->MarkAsContextSpecializing();
} else if (FLAG_turbo_type_feedback) {
info()->MarkAsTypeFeedbackEnabled();
if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
// Context specialization folds-in the context, so no sharing can occur.
- if (code->is_turbofanned() && info->is_context_specializing()) return;
+ if (info->is_context_specializing()) return;
+ // Frame specialization implies context specialization.
+ DCHECK(!info->is_frame_specializing());
// Do not cache bound functions.
Handle<JSFunction> function = info->closure();
MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
Handle<Code> current_code,
ConcurrencyMode mode,
- BailoutId osr_ast_id) {
+ BailoutId osr_ast_id,
+ JavaScriptFrame* osr_frame) {
Handle<Code> cached_code;
if (GetCodeFromOptimizedCodeMap(
function, osr_ast_id).ToHandle(&cached_code)) {
return isolate->builtins()->InOptimizationQueue();
}
} else {
+ info->set_osr_frame(osr_frame);
if (GetOptimizedCodeNow(info.get())) return info->code();
}
class AstValueFactory;
class HydrogenCodeStub;
+class JavaScriptFrame;
class ParseInfo;
class ScriptData;
kCompilingForDebugging = 1 << 7,
kSerializing = 1 << 8,
kContextSpecializing = 1 << 9,
- kInliningEnabled = 1 << 10,
- kTypingEnabled = 1 << 11,
- kDisableFutureOptimization = 1 << 12,
- kSplittingEnabled = 1 << 13,
- kTypeFeedbackEnabled = 1 << 14,
- kDeoptimizationEnabled = 1 << 15,
- kSourcePositionsEnabled = 1 << 16,
- kFirstCompile = 1 << 17,
+ kFrameSpecializing = 1 << 10,
+ kInliningEnabled = 1 << 11,
+ kTypingEnabled = 1 << 12,
+ kDisableFutureOptimization = 1 << 13,
+ kSplittingEnabled = 1 << 14,
+ kTypeFeedbackEnabled = 1 << 15,
+ kDeoptimizationEnabled = 1 << 16,
+ kSourcePositionsEnabled = 1 << 17,
+ kFirstCompile = 1 << 18,
};
explicit CompilationInfo(ParseInfo* parse_info);
bool is_context_specializing() const { return GetFlag(kContextSpecializing); }
+ void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
+
+ bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
+
void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
bool is_type_feedback_enabled() const {
DCHECK(height >= 0);
osr_expr_stack_height_ = height;
}
+ JavaScriptFrame* osr_frame() const { return osr_frame_; }
+ void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
#if DEBUG
void PrintAstForTesting();
int osr_expr_stack_height_;
+ // The current OSR frame for specialization or {nullptr}.
+ JavaScriptFrame* osr_frame_ = nullptr;
+
Type::FunctionType* function_type_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
// In the latter case, return the InOptimizationQueue builtin. On failure,
// return the empty handle.
MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
- Handle<JSFunction> function,
- Handle<Code> current_code,
- ConcurrencyMode mode,
- BailoutId osr_ast_id = BailoutId::None());
+ Handle<JSFunction> function, Handle<Code> current_code,
+ ConcurrencyMode mode, BailoutId osr_ast_id = BailoutId::None(),
+ JavaScriptFrame* osr_frame = nullptr);
// Generate and return code from previously queued optimization job.
// On failure, return the empty handle.
--- /dev/null
+// Copyright 2015 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.
+
+#include "src/compiler/js-frame-specialization.h"
+
+#include "src/compiler/js-graph.h"
+#include "src/compiler/linkage.h"
+#include "src/frames-inl.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+Reduction JSFrameSpecialization::Reduce(Node* node) {
+ switch (node->opcode()) {
+ case IrOpcode::kOsrValue:
+ return ReduceOsrValue(node);
+ case IrOpcode::kParameter:
+ return ReduceParameter(node);
+ default:
+ break;
+ }
+ return NoChange();
+}
+
+
+Reduction JSFrameSpecialization::ReduceOsrValue(Node* node) {
+ DCHECK_EQ(IrOpcode::kOsrValue, node->opcode());
+ DisallowHeapAllocation no_gc;
+ Object* object;
+ int const index = OpParameter<int>(node);
+ int const parameters_count = frame()->ComputeParametersCount() + 1;
+ if (index == Linkage::kOsrContextSpillSlotIndex) {
+ object = frame()->context();
+ } else if (index >= parameters_count) {
+ object = frame()->GetExpression(index - parameters_count);
+ } else {
+ // The OsrValue index 0 is the receiver.
+ object = index ? frame()->GetParameter(index - 1) : frame()->receiver();
+ }
+ return Replace(jsgraph()->Constant(handle(object, isolate())));
+}
+
+
+Reduction JSFrameSpecialization::ReduceParameter(Node* node) {
+ DCHECK_EQ(IrOpcode::kParameter, node->opcode());
+ DisallowHeapAllocation no_gc;
+ Object* object;
+ int const index = ParameterIndexOf(node->op());
+ int const parameters_count = frame()->ComputeParametersCount() + 1;
+ if (index == Linkage::kJSFunctionCallClosureParamIndex) {
+ object = frame()->function();
+ } else if (index == parameters_count) {
+ // The Parameter index (arity + 1) is the context.
+ object = frame()->context();
+ } else {
+ // The Parameter index 0 is the receiver.
+ object = index ? frame()->GetParameter(index - 1) : frame()->receiver();
+ }
+ return Replace(jsgraph()->Constant(handle(object, isolate())));
+}
+
+
+Isolate* JSFrameSpecialization::isolate() const { return jsgraph()->isolate(); }
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
--- /dev/null
+// Copyright 2015 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.
+
+#ifndef V8_COMPILER_JS_FRAME_SPECIALIZATION_H_
+#define V8_COMPILER_JS_FRAME_SPECIALIZATION_H_
+
+#include "src/compiler/graph-reducer.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// Forward declarations.
+class JSGraph;
+
+
+class JSFrameSpecialization final : public Reducer {
+ public:
+ JSFrameSpecialization(JavaScriptFrame const* frame, JSGraph* jsgraph)
+ : frame_(frame), jsgraph_(jsgraph) {}
+ ~JSFrameSpecialization() final {}
+
+ Reduction Reduce(Node* node) final;
+
+ private:
+ Reduction ReduceOsrValue(Node* node);
+ Reduction ReduceParameter(Node* node);
+
+ Isolate* isolate() const;
+ JavaScriptFrame const* frame() const { return frame_; }
+ JSGraph* jsgraph() const { return jsgraph_; }
+
+ JavaScriptFrame const* const frame_;
+ JSGraph* const jsgraph_;
+
+ DISALLOW_COPY_AND_ASSIGN(JSFrameSpecialization);
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_JS_FRAME_SPECIALIZATION_H_
#include "src/compiler/instruction-selector.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-context-specialization.h"
+#include "src/compiler/js-frame-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-inlining.h"
#include "src/compiler/js-intrinsic-lowering.h"
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
JSContextSpecializer context_specializer(&graph_reducer, data->jsgraph());
+ JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
+ data->jsgraph());
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
? JSInliner::kGeneralInlining
: JSInliner::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph());
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &common_reducer);
+ if (data->info()->is_frame_specializing()) {
+ AddReducer(data, &graph_reducer, &frame_specialization);
+ }
if (data->info()->is_context_specializing()) {
AddReducer(data, &graph_reducer, &context_specializer);
}
BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
DCHECK(!ast_id.IsNone());
- Compiler::ConcurrencyMode mode =
- isolate->concurrent_osr_enabled() &&
- (function->shared()->ast_node_count() > 512)
- ? Compiler::CONCURRENT
- : Compiler::NOT_CONCURRENT;
+ // Disable concurrent OSR for asm.js, to enable frame specialization.
+ Compiler::ConcurrencyMode mode = (isolate->concurrent_osr_enabled() &&
+ !function->shared()->asm_function() &&
+ function->shared()->ast_node_count() > 512)
+ ? Compiler::CONCURRENT
+ : Compiler::NOT_CONCURRENT;
Handle<Code> result = Handle<Code>::null();
OptimizedCompileJob* job = NULL;
function->PrintName();
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- MaybeHandle<Code> maybe_result =
- Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
+ MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
+ function, caller_code, mode, ast_id,
+ (mode == Compiler::NOT_CONCURRENT) ? frame : nullptr);
if (maybe_result.ToHandle(&result) &&
result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
// Optimization is queued. Return to check later.
'../../src/compiler/js-builtin-reducer.h',
'../../src/compiler/js-context-specialization.cc',
'../../src/compiler/js-context-specialization.h',
+ '../../src/compiler/js-frame-specialization.cc',
+ '../../src/compiler/js-frame-specialization.h',
'../../src/compiler/js-generic-lowering.cc',
'../../src/compiler/js-generic-lowering.h',
'../../src/compiler/js-graph.cc',