Index: runtime/vm/compiler.cc |
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
index 0c47e544f612c25222f1257f773035f3601fb962..d746b53fe6918a2a1b541333b26f0918f8fce323 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,102 @@ DEFINE_FLAG(bool, verify_compiler, false, |
DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
DECLARE_FLAG(bool, trace_patching); |
+DECLARE_FLAG(bool, trace_irregexp); |
+ |
+// TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove |
+// separate helpers functions & `optimizing` args. |
+class CompilationPipeline : public ZoneAllocated { |
+ public: |
+ static CompilationPipeline* New(Isolate* isolate, const Function& function); |
+ |
+ virtual void ParseFunction(ParsedFunction* parsed_function) = 0; |
+ virtual FlowGraph* BuildFlowGraph( |
+ ParsedFunction* parsed_function, |
+ const ZoneGrowableArray<const ICData*>& ic_data_array, |
+ intptr_t osr_id) = 0; |
+ virtual void FinalizeCompilation() = 0; |
+ virtual ~CompilationPipeline() { } |
+}; |
+ |
+ |
+class DartCompilationPipeline : public CompilationPipeline { |
+ public: |
+ virtual void ParseFunction(ParsedFunction* parsed_function) { |
+ Parser::ParseFunction(parsed_function); |
+ parsed_function->AllocateVariables(); |
+ } |
+ |
+ virtual FlowGraph* BuildFlowGraph( |
+ ParsedFunction* parsed_function, |
+ const 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 FinalizeCompilation() { } |
+}; |
+ |
+ |
+class IrregexpCompilationPipeline : public CompilationPipeline { |
+ public: |
+ explicit IrregexpCompilationPipeline(Isolate* isolate) |
+ : backtrack_goto_(NULL), |
+ isolate_(isolate) { } |
+ |
+ virtual void ParseFunction(ParsedFunction* parsed_function) { |
+ RegExpParser::ParseFunction(parsed_function); |
+ // Variables are allocated after compilation. |
+ } |
+ |
+ virtual FlowGraph* BuildFlowGraph( |
+ ParsedFunction* parsed_function, |
+ const 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); |
+ backtrack_goto_ = result.backtrack_goto; |
+ |
+ // 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 FinalizeCompilation() { |
+ backtrack_goto_->ComputeOffsetTable(isolate_); |
+ } |
+ |
+ private: |
+ IndirectGotoInstr* backtrack_goto_; |
+ Isolate* isolate_; |
+}; |
+ |
+CompilationPipeline* CompilationPipeline::New(Isolate* isolate, |
+ const Function& function) { |
+ if (function.IsIrregexpFunction()) { |
+ return new(isolate) IrregexpCompilationPipeline(isolate); |
+ } else { |
+ return new(isolate) DartCompilationPipeline(); |
+ } |
+} |
+ |
// Compile a function. Should call only if the function has not been compiled. |
// Arg0: function object. |
@@ -264,7 +362,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 +420,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 || |
@@ -583,6 +679,7 @@ static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, |
&CompilerStats::graphcompiler_timer, |
isolate); |
graph_compiler.CompileGraph(); |
+ pipeline->FinalizeCompilation(); |
} |
{ |
TimerScope timer(FLAG_compiler_stats, |
@@ -815,7 +912,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(); |
@@ -837,12 +935,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. |
@@ -896,7 +995,8 @@ 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); |
+ CompilationPipeline* pipeline = CompilationPipeline::New(isolate, function); |
+ return CompileFunctionHelper(pipeline, function, false, Isolate::kNoDeoptId); |
} |
@@ -904,7 +1004,8 @@ RawError* Compiler::CompileOptimizedFunction(Isolate* isolate, |
const Function& function, |
intptr_t osr_id) { |
VMTagScope tagScope(isolate, VMTag::kCompileOptimizedTagId); |
- return CompileFunctionHelper(function, true, osr_id); |
+ CompilationPipeline* pipeline = CompilationPipeline::New(isolate, function); |
+ return CompileFunctionHelper(pipeline, function, true, osr_id); |
} |
@@ -915,7 +1016,11 @@ RawError* Compiler::CompileParsedFunction( |
LongJumpScope jump; |
if (setjmp(*jump.Set()) == 0) { |
// Non-optimized code generator. |
- CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); |
+ DartCompilationPipeline pipeline; |
+ CompileParsedFunctionHelper(&pipeline, |
+ parsed_function, |
+ false, |
+ Isolate::kNoDeoptId); |
if (FLAG_disassemble) { |
DisassembleCode(parsed_function->function(), false); |
} |
@@ -992,7 +1097,11 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { |
parsed_function->AllocateVariables(); |
// Non-optimized code generator. |
- CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); |
+ DartCompilationPipeline pipeline; |
+ CompileParsedFunctionHelper(&pipeline, |
+ parsed_function, |
+ false, |
+ Isolate::kNoDeoptId); |
// Invoke the function to evaluate the expression. |
const Function& initializer = parsed_function->function(); |
@@ -1053,7 +1162,11 @@ RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { |
parsed_function->AllocateVariables(); |
// Non-optimized code generator. |
- CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); |
+ DartCompilationPipeline pipeline; |
+ CompileParsedFunctionHelper(&pipeline, |
+ parsed_function, |
+ false, |
+ Isolate::kNoDeoptId); |
const Object& result = PassiveObject::Handle( |
DartEntry::InvokeFunction(func, Object::empty_array())); |