| Index: runtime/vm/compiler.cc
|
| diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
|
| index 959dd0fd85b466dc575e7ee546f8e7145f1d403c..97530c9d8c8a70d9759d86c3bdb6138b4fadee59 100644
|
| --- a/runtime/vm/compiler.cc
|
| +++ b/runtime/vm/compiler.cc
|
| @@ -29,6 +29,8 @@
|
| #include "vm/object_store.h"
|
| #include "vm/os.h"
|
| #include "vm/parser.h"
|
| +#include "vm/regexp_parser.h"
|
| +#include "vm/regexp_assembler.h"
|
| #include "vm/scanner.h"
|
| #include "vm/symbols.h"
|
| #include "vm/tags.h"
|
| @@ -63,6 +65,94 @@ DEFINE_FLAG(bool, verify_compiler, false,
|
|
|
| DECLARE_FLAG(bool, trace_failed_optimization_attempts);
|
| DECLARE_FLAG(bool, trace_patching);
|
| +DECLARE_FLAG(bool, trace_irregexp);
|
| +
|
| +// TODO(jgruber): Factor out unoptimizing/optimizing pipelines and remove
|
| +// separate helpers functions & `optimizing` args.
|
| +class CompilationPipeline : public ValueObject {
|
| + public:
|
| + virtual void ParseFunction(ParsedFunction* parsed_function) = 0;
|
| + virtual FlowGraph* BuildFlowGraph(
|
| + ParsedFunction* parsed_function,
|
| + ZoneGrowableArray<const ICData*>* ic_data_array,
|
| + intptr_t osr_id) = 0;
|
| + virtual void CompileGraph(FlowGraphCompiler* graph_compiler) = 0;
|
| + virtual ~CompilationPipeline() { }
|
| +};
|
| +
|
| +
|
| +class StandardCompilationPipeline : public CompilationPipeline {
|
| + public:
|
| + virtual void ParseFunction(ParsedFunction* parsed_function) {
|
| + Parser::ParseFunction(parsed_function);
|
| + parsed_function->AllocateVariables();
|
| + }
|
| +
|
| + virtual FlowGraph* BuildFlowGraph(
|
| + ParsedFunction* parsed_function,
|
| + ZoneGrowableArray<const ICData*>* ic_data_array,
|
| + intptr_t osr_id) {
|
| + // Build the flow graph.
|
| + FlowGraphBuilder builder(parsed_function,
|
| + *ic_data_array,
|
| + NULL, // NULL = not inlining.
|
| + osr_id);
|
| +
|
| + return builder.BuildGraph();
|
| + }
|
| +
|
| + virtual void CompileGraph(FlowGraphCompiler* graph_compiler) {
|
| + graph_compiler->CompileGraph();
|
| + }
|
| +};
|
| +
|
| +
|
| +class IrregexpCompilationPipeline : public StandardCompilationPipeline {
|
| + public:
|
| + explicit IrregexpCompilationPipeline(Isolate* isolate)
|
| + : macro_assembler_(NULL),
|
| + isolate_(isolate) { }
|
| +
|
| + virtual void ParseFunction(ParsedFunction* parsed_function) {
|
| + RegExpParser::ParseFunction(parsed_function);
|
| + // Variables are allocated after compilation.
|
| + }
|
| +
|
| + virtual FlowGraph* BuildFlowGraph(
|
| + ParsedFunction* parsed_function,
|
| + ZoneGrowableArray<const ICData*>* ic_data_array,
|
| + intptr_t osr_id) {
|
| + // Compile to the dart IR.
|
| + RegExpEngine::CompilationResult result =
|
| + RegExpEngine::Compile(parsed_function->regexp_compile_data(),
|
| + parsed_function,
|
| + ic_data_array);
|
| + macro_assembler_ = result.macro_assembler;
|
| +
|
| + // Allocate variables now that we know the number of locals.
|
| + parsed_function->AllocateIrregexpVariables(result.num_stack_locals);
|
| +
|
| + // Build the flow graph.
|
| + FlowGraphBuilder builder(parsed_function,
|
| + *ic_data_array,
|
| + NULL, // NULL = not inlining.
|
| + osr_id);
|
| +
|
| + return new(isolate_) FlowGraph(builder,
|
| + result.graph_entry,
|
| + result.num_blocks);
|
| + }
|
| +
|
| + virtual void CompileGraph(FlowGraphCompiler* graph_compiler) {
|
| + graph_compiler->CompileGraph();
|
| + macro_assembler_->FinalizeBlockOffsetTable();
|
| + }
|
| +
|
| + private:
|
| + IRRegExpMacroAssembler* macro_assembler_;
|
| + Isolate* isolate_;
|
| +};
|
| +
|
|
|
| // Compile a function. Should call only if the function has not been compiled.
|
| // Arg0: function object.
|
| @@ -264,7 +354,8 @@ RawError* Compiler::CompileClass(const Class& cls) {
|
|
|
|
|
| // Return false if bailed out.
|
| -static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function,
|
| +static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
|
| + ParsedFunction* parsed_function,
|
| bool optimized,
|
| intptr_t osr_id) {
|
| const Function& function = parsed_function->function();
|
| @@ -321,12 +412,9 @@ static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function,
|
| }
|
| }
|
|
|
| - // Build the flow graph.
|
| - FlowGraphBuilder builder(parsed_function,
|
| - *ic_data_array,
|
| - NULL, // NULL = not inlining.
|
| - osr_id);
|
| - flow_graph = builder.BuildGraph();
|
| + flow_graph = pipeline->BuildFlowGraph(parsed_function,
|
| + ic_data_array,
|
| + osr_id);
|
| }
|
|
|
| if (FLAG_print_flow_graph ||
|
| @@ -582,7 +670,7 @@ static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function,
|
| TimerScope timer(FLAG_compiler_stats,
|
| &CompilerStats::graphcompiler_timer,
|
| isolate);
|
| - graph_compiler.CompileGraph();
|
| + pipeline->CompileGraph(&graph_compiler);
|
| }
|
| {
|
| TimerScope timer(FLAG_compiler_stats,
|
| @@ -816,7 +904,8 @@ static void DisassembleCode(const Function& function, bool optimized) {
|
| }
|
|
|
|
|
| -static RawError* CompileFunctionHelper(const Function& function,
|
| +static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
| + const Function& function,
|
| bool optimized,
|
| intptr_t osr_id) {
|
| Isolate* isolate = Isolate::Current();
|
| @@ -838,12 +927,13 @@ static RawError* CompileFunctionHelper(const Function& function,
|
| }
|
| {
|
| HANDLESCOPE(isolate);
|
| - Parser::ParseFunction(parsed_function);
|
| - parsed_function->AllocateVariables();
|
| + pipeline->ParseFunction(parsed_function);
|
| }
|
|
|
| - const bool success =
|
| - CompileParsedFunctionHelper(parsed_function, optimized, osr_id);
|
| + const bool success = CompileParsedFunctionHelper(pipeline,
|
| + parsed_function,
|
| + optimized,
|
| + osr_id);
|
| if (!success) {
|
| if (optimized) {
|
| // Optimizer bailed out. Disable optimizations and to never try again.
|
| @@ -897,7 +987,15 @@ static RawError* CompileFunctionHelper(const Function& function,
|
| RawError* Compiler::CompileFunction(Isolate* isolate,
|
| const Function& function) {
|
| VMTagScope tagScope(isolate, VMTag::kCompileUnoptimizedTagId);
|
| - return CompileFunctionHelper(function, false, Isolate::kNoDeoptId);
|
| + if (function.IsIrregexpFunction()) {
|
| + IrregexpCompilationPipeline pipeline(isolate);
|
| + return CompileFunctionHelper(
|
| + &pipeline, function, false, Isolate::kNoDeoptId);
|
| + } else {
|
| + StandardCompilationPipeline pipeline;
|
| + return CompileFunctionHelper(
|
| + &pipeline, function, false, Isolate::kNoDeoptId);
|
| + }
|
| }
|
|
|
|
|
| @@ -905,7 +1003,13 @@ RawError* Compiler::CompileOptimizedFunction(Isolate* isolate,
|
| const Function& function,
|
| intptr_t osr_id) {
|
| VMTagScope tagScope(isolate, VMTag::kCompileOptimizedTagId);
|
| - return CompileFunctionHelper(function, true, osr_id);
|
| + if (function.IsIrregexpFunction()) {
|
| + IrregexpCompilationPipeline pipeline(isolate);
|
| + return CompileFunctionHelper(&pipeline, function, true, osr_id);
|
| + } else {
|
| + StandardCompilationPipeline pipeline;
|
| + return CompileFunctionHelper(&pipeline, function, true, osr_id);
|
| + }
|
| }
|
|
|
|
|
| @@ -916,7 +1020,11 @@ RawError* Compiler::CompileParsedFunction(
|
| LongJumpScope jump;
|
| if (setjmp(*jump.Set()) == 0) {
|
| // Non-optimized code generator.
|
| - CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
|
| + StandardCompilationPipeline pipeline;
|
| + CompileParsedFunctionHelper(&pipeline,
|
| + parsed_function,
|
| + false,
|
| + Isolate::kNoDeoptId);
|
| if (FLAG_disassemble) {
|
| DisassembleCode(parsed_function->function(), false);
|
| }
|
| @@ -993,7 +1101,11 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
|
|
|
| parsed_function->AllocateVariables();
|
| // Non-optimized code generator.
|
| - CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
|
| + StandardCompilationPipeline pipeline;
|
| + CompileParsedFunctionHelper(&pipeline,
|
| + parsed_function,
|
| + false,
|
| + Isolate::kNoDeoptId);
|
|
|
| // Invoke the function to evaluate the expression.
|
| const Function& initializer = parsed_function->function();
|
| @@ -1053,7 +1165,11 @@ RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
|
| parsed_function->AllocateVariables();
|
|
|
| // Non-optimized code generator.
|
| - CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
|
| + StandardCompilationPipeline pipeline;
|
| + CompileParsedFunctionHelper(&pipeline,
|
| + parsed_function,
|
| + false,
|
| + Isolate::kNoDeoptId);
|
|
|
| const Object& result = PassiveObject::Handle(
|
| DartEntry::InvokeFunction(func, Object::empty_array()));
|
|
|