OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/code_index_table.h" | 10 #include "vm/code_index_table.h" |
11 #include "vm/code_patcher.h" | 11 #include "vm/code_patcher.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/disassembler.h" | 13 #include "vm/disassembler.h" |
14 #include "vm/exceptions.h" | |
15 #include "vm/flags.h" | 14 #include "vm/flags.h" |
16 #include "vm/longjump.h" | |
17 #include "vm/object.h" | 15 #include "vm/object.h" |
18 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
19 #include "vm/opt_code_generator.h" | 17 #include "vm/opt_code_generator.h" |
20 #include "vm/os.h" | 18 #include "vm/os.h" |
21 #include "vm/parser.h" | 19 #include "vm/parser.h" |
22 #include "vm/scanner.h" | 20 #include "vm/scanner.h" |
23 #include "vm/timer.h" | 21 #include "vm/timer.h" |
24 | 22 |
25 namespace dart { | 23 namespace dart { |
26 | 24 |
27 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); | 25 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); |
28 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 26 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
29 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, | 27 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, |
30 "How many times we allow deoptimization before we disallow" | 28 "How many times we allow deoptimization before we disallow" |
31 " certain optimizations"); | 29 " certain optimizations"); |
32 | 30 |
33 | 31 |
34 // Compile a function. Should call only if the function has not been compiled. | 32 // Compile a function. Should call only if the function has not been compiled. |
35 // Arg0: function object. | 33 // Arg0: function object. |
36 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 34 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
37 ASSERT(arguments.Count() == kCompileFunctionRuntimeEntry.argument_count()); | 35 ASSERT(arguments.Count() == kCompileFunctionRuntimeEntry.argument_count()); |
38 const Function& function = Function::CheckedHandle(arguments.At(0)); | 36 const Function& function = Function::CheckedHandle(arguments.At(0)); |
39 ASSERT(!function.HasCode()); | 37 ASSERT(!function.HasCode()); |
40 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 38 Compiler::CompileFunction(function); |
41 if (!error.IsNull()) { | |
42 Exceptions::PropagateError(error); | |
43 } | |
44 } | 39 } |
45 | 40 |
46 | 41 |
47 // Extracts IC data associated with a node id. | 42 // Extracts IC data associated with a node id. |
48 // TODO(srdjan): Check performance impact of node id search loop. | 43 // TODO(srdjan): Check performance impact of node id search loop. |
49 static void ExtractTypeFeedback(const Code& code, | 44 static void ExtractTypeFeedback(const Code& code, |
50 SequenceNode* sequence_node) { | 45 SequenceNode* sequence_node) { |
51 ASSERT(!code.IsNull() && !code.is_optimized()); | 46 ASSERT(!code.IsNull() && !code.is_optimized()); |
52 GrowableArray<AstNode*> all_nodes; | 47 GrowableArray<AstNode*> all_nodes; |
53 sequence_node->CollectAllNodes(&all_nodes); | 48 sequence_node->CollectAllNodes(&all_nodes); |
54 GrowableArray<intptr_t> node_ids; | 49 GrowableArray<intptr_t> node_ids; |
55 GrowableArray<const Array*> arrays; | 50 GrowableArray<const Array*> arrays; |
56 code.ExtractIcDataArraysAtCalls(&node_ids, &arrays); | 51 code.ExtractIcDataArraysAtCalls(&node_ids, &arrays); |
57 for (intptr_t i = 0; i < node_ids.length(); i++) { | 52 for (intptr_t i = 0; i < node_ids.length(); i++) { |
58 intptr_t node_id = node_ids[i]; | 53 intptr_t node_id = node_ids[i]; |
59 bool found_node = false; | 54 bool found_node = false; |
60 for (intptr_t n = 0; n < all_nodes.length(); n++) { | 55 for (intptr_t n = 0; n < all_nodes.length(); n++) { |
61 if (all_nodes[n]->HasId(node_id)) { | 56 if (all_nodes[n]->HasId(node_id)) { |
62 found_node = true; | 57 found_node = true; |
63 // Make sure we assign ic data array only once. | 58 // Make sure we assign ic data array only once. |
64 ASSERT(all_nodes[n]->ICDataAtId(node_id).NumberOfChecks() == 0); | 59 ASSERT(all_nodes[n]->ICDataAtId(node_id).NumberOfChecks() == 0); |
65 all_nodes[n]->SetIcDataArrayAtId(node_id, *arrays[i]); | 60 all_nodes[n]->SetIcDataArrayAtId(node_id, *arrays[i]); |
66 } | 61 } |
67 } | 62 } |
68 ASSERT(found_node); | 63 ASSERT(found_node); |
69 } | 64 } |
70 } | 65 } |
71 | 66 |
72 | 67 |
73 RawError* Compiler::Compile(const Library& library, const Script& script) { | 68 void Compiler::Compile(const Library& library, const Script& script) { |
74 Isolate* isolate = Isolate::Current(); | 69 if (FLAG_trace_compiler) { |
75 Error& error = Error::Handle(); | 70 HANDLESCOPE(Isolate::Current()); |
76 LongJump* base = isolate->long_jump_base(); | 71 const String& script_url = String::Handle(script.url()); |
77 LongJump jump; | 72 // TODO(iposva): Extract script kind. |
78 isolate->set_long_jump_base(&jump); | 73 OS::Print("Compiling %s '%s'\n", "", script_url.ToCString()); |
79 if (setjmp(*jump.Set()) == 0) { | 74 } |
| 75 const String& library_key = String::Handle(library.private_key()); |
| 76 script.Tokenize(library_key); |
| 77 Parser::ParseCompilationUnit(library, script); |
| 78 } |
| 79 |
| 80 |
| 81 static void CompileFunctionHelper(const Function& function, bool optimized) { |
| 82 TIMERSCOPE(time_compilation); |
| 83 ParsedFunction parsed_function(function); |
| 84 const char* function_fullname = function.ToFullyQualifiedCString(); |
| 85 if (FLAG_trace_compiler) { |
| 86 OS::Print("Compiling %sfunction: '%s' @ token %d\n", |
| 87 (optimized ? "optimized " : ""), |
| 88 function_fullname, |
| 89 function.token_index()); |
| 90 } |
| 91 Parser::ParseFunction(&parsed_function); |
| 92 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table(); |
| 93 ASSERT(code_index_table != NULL); |
| 94 Assembler assembler; |
| 95 if (optimized) { |
| 96 // Transition to optimized code only from unoptimized code ... for now. |
| 97 ASSERT(function.HasCode()); |
| 98 ASSERT(!Code::Handle(function.code()).is_optimized()); |
| 99 // Do not use type feedback to optimize a function that was deoptimized. |
| 100 if (parsed_function.function().deoptimization_counter() < |
| 101 FLAG_deoptimization_counter_threshold) { |
| 102 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), |
| 103 parsed_function.node_sequence()); |
| 104 } |
| 105 OptimizingCodeGenerator code_gen(&assembler, parsed_function); |
| 106 code_gen.GenerateCode(); |
| 107 Code& code = Code::Handle( |
| 108 Code::FinalizeCode(function_fullname, &assembler)); |
| 109 code.set_is_optimized(true); |
| 110 code_gen.FinalizePcDescriptors(code); |
| 111 code_gen.FinalizeExceptionHandlers(code); |
| 112 function.SetCode(code); |
| 113 code_index_table->AddFunction(function); |
| 114 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
80 if (FLAG_trace_compiler) { | 115 if (FLAG_trace_compiler) { |
81 HANDLESCOPE(isolate); | 116 OS::Print("--> patching entry 0x%x\n", |
82 const String& script_url = String::Handle(script.url()); | 117 Code::Handle(function.unoptimized_code()).EntryPoint()); |
83 // TODO(iposva): Extract script kind. | 118 } |
84 OS::Print("Compiling %s '%s'\n", "", script_url.ToCString()); | |
85 } | |
86 const String& library_key = String::Handle(library.private_key()); | |
87 script.Tokenize(library_key); | |
88 Parser::ParseCompilationUnit(library, script); | |
89 } else { | 119 } else { |
90 error = isolate->object_store()->sticky_error(); | 120 // Unoptimized code. |
91 isolate->object_store()->clear_sticky_error(); | 121 if (Code::Handle(function.unoptimized_code()).IsNull()) { |
92 } | 122 ASSERT(Code::Handle(function.code()).IsNull()); |
93 isolate->set_long_jump_base(base); | 123 // Compiling first time. |
94 return error.raw(); | 124 CodeGenerator code_gen(&assembler, parsed_function); |
95 } | |
96 | |
97 | |
98 static RawError* CompileFunctionHelper(const Function& function, | |
99 bool optimized) { | |
100 Isolate* isolate = Isolate::Current(); | |
101 Error& error = Error::Handle(); | |
102 LongJump* base = isolate->long_jump_base(); | |
103 LongJump jump; | |
104 isolate->set_long_jump_base(&jump); | |
105 if (setjmp(*jump.Set()) == 0) { | |
106 TIMERSCOPE(time_compilation); | |
107 ParsedFunction parsed_function(function); | |
108 const char* function_fullname = function.ToFullyQualifiedCString(); | |
109 if (FLAG_trace_compiler) { | |
110 OS::Print("Compiling %sfunction: '%s' @ token %d\n", | |
111 (optimized ? "optimized " : ""), | |
112 function_fullname, | |
113 function.token_index()); | |
114 } | |
115 Parser::ParseFunction(&parsed_function); | |
116 CodeIndexTable* code_index_table = isolate->code_index_table(); | |
117 ASSERT(code_index_table != NULL); | |
118 Assembler assembler; | |
119 if (optimized) { | |
120 // Transition to optimized code only from unoptimized code ... for now. | |
121 ASSERT(function.HasCode()); | |
122 ASSERT(!Code::Handle(function.code()).is_optimized()); | |
123 // Do not use type feedback to optimize a function that was deoptimized. | |
124 if (parsed_function.function().deoptimization_counter() < | |
125 FLAG_deoptimization_counter_threshold) { | |
126 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), | |
127 parsed_function.node_sequence()); | |
128 } | |
129 OptimizingCodeGenerator code_gen(&assembler, parsed_function); | |
130 code_gen.GenerateCode(); | 125 code_gen.GenerateCode(); |
131 Code& code = Code::Handle( | 126 const Code& code = |
132 Code::FinalizeCode(function_fullname, &assembler)); | 127 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); |
133 code.set_is_optimized(true); | 128 code.set_is_optimized(false); |
134 code_gen.FinalizePcDescriptors(code); | 129 code_gen.FinalizePcDescriptors(code); |
| 130 code_gen.FinalizeVarDescriptors(code); |
135 code_gen.FinalizeExceptionHandlers(code); | 131 code_gen.FinalizeExceptionHandlers(code); |
| 132 function.set_unoptimized_code(code); |
136 function.SetCode(code); | 133 function.SetCode(code); |
| 134 ASSERT(CodePatcher::CodeIsPatchable(code)); |
137 code_index_table->AddFunction(function); | 135 code_index_table->AddFunction(function); |
138 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | 136 } else { |
| 137 // Disable optimized code. |
| 138 const Code& optimized_code = Code::Handle(function.code()); |
| 139 ASSERT(optimized_code.is_optimized()); |
| 140 CodePatcher::PatchEntry(Code::Handle(function.code())); |
139 if (FLAG_trace_compiler) { | 141 if (FLAG_trace_compiler) { |
140 OS::Print("--> patching entry 0x%x\n", | 142 OS::Print("--> patching entry 0x%x\n", |
141 Code::Handle(function.unoptimized_code()).EntryPoint()); | 143 Code::Handle(function.unoptimized_code()).EntryPoint()); |
142 } | 144 } |
143 } else { | 145 // Use previously compiled code. |
144 // Unoptimized code. | 146 function.SetCode(Code::Handle(function.unoptimized_code())); |
145 if (Code::Handle(function.unoptimized_code()).IsNull()) { | 147 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); |
146 ASSERT(Code::Handle(function.code()).IsNull()); | 148 if (FLAG_trace_compiler) { |
147 // Compiling first time. | 149 OS::Print("--> restoring entry at 0x%x\n", |
148 CodeGenerator code_gen(&assembler, parsed_function); | 150 Code::Handle(function.unoptimized_code()).EntryPoint()); |
149 code_gen.GenerateCode(); | |
150 const Code& code = | |
151 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | |
152 code.set_is_optimized(false); | |
153 code_gen.FinalizePcDescriptors(code); | |
154 code_gen.FinalizeVarDescriptors(code); | |
155 code_gen.FinalizeExceptionHandlers(code); | |
156 function.set_unoptimized_code(code); | |
157 function.SetCode(code); | |
158 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
159 code_index_table->AddFunction(function); | |
160 } else { | |
161 // Disable optimized code. | |
162 const Code& optimized_code = Code::Handle(function.code()); | |
163 ASSERT(optimized_code.is_optimized()); | |
164 CodePatcher::PatchEntry(Code::Handle(function.code())); | |
165 if (FLAG_trace_compiler) { | |
166 OS::Print("--> patching entry 0x%x\n", | |
167 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
168 } | |
169 // Use previously compiled code. | |
170 function.SetCode(Code::Handle(function.unoptimized_code())); | |
171 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | |
172 if (FLAG_trace_compiler) { | |
173 OS::Print("--> restoring entry at 0x%x\n", | |
174 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
175 } | |
176 } | 151 } |
177 } | 152 } |
178 if (FLAG_trace_compiler) { | 153 } |
179 OS::Print("--> '%s' entry: 0x%x\n", | 154 if (FLAG_trace_compiler) { |
180 function_fullname, Code::Handle(function.code()).EntryPoint()); | 155 OS::Print("--> '%s' entry: 0x%x\n", |
181 } | 156 function_fullname, Code::Handle(function.code()).EntryPoint()); |
182 if (FLAG_disassemble) { | 157 } |
183 OS::Print("Code for %sfunction '%s' {\n", | 158 if (FLAG_disassemble) { |
184 optimized ? "optimized " : "", function_fullname); | 159 OS::Print("Code for %sfunction '%s' {\n", |
185 const Code& code = Code::Handle(function.code()); | 160 optimized ? "optimized " : "", function_fullname); |
186 const Instructions& instructions = | 161 const Code& code = Code::Handle(function.code()); |
187 Instructions::Handle(code.instructions()); | 162 const Instructions& instructions = |
188 uword start = instructions.EntryPoint(); | 163 Instructions::Handle(code.instructions()); |
189 Disassembler::Disassemble(start, start + assembler.CodeSize()); | 164 uword start = instructions.EntryPoint(); |
190 OS::Print("}\n"); | 165 Disassembler::Disassemble(start, start + assembler.CodeSize()); |
191 OS::Print("Pointer offsets for function: {\n"); | 166 OS::Print("}\n"); |
192 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { | 167 OS::Print("Pointer offsets for function: {\n"); |
193 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | 168 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { |
194 Object& obj = Object::Handle(); | 169 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
195 obj = *reinterpret_cast<RawObject**>(addr); | 170 Object& obj = Object::Handle(); |
196 OS::Print(" %d : 0x%x '%s'\n", | 171 obj = *reinterpret_cast<RawObject**>(addr); |
197 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 172 OS::Print(" %d : 0x%x '%s'\n", |
198 } | 173 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
199 OS::Print("}\n"); | 174 } |
200 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); | 175 OS::Print("}\n"); |
201 OS::Print("(pc, kind, id, try-index, token-index)\n"); | 176 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); |
202 const PcDescriptors& descriptors = | 177 OS::Print("(pc, kind, id, try-index, token-index)\n"); |
203 PcDescriptors::Handle(code.pc_descriptors()); | 178 const PcDescriptors& descriptors = |
204 OS::Print("%s", descriptors.ToCString()); | 179 PcDescriptors::Handle(code.pc_descriptors()); |
205 OS::Print("}\n"); | 180 OS::Print("%s", descriptors.ToCString()); |
206 OS::Print("Variable Descriptors for function '%s' {\n", | 181 OS::Print("}\n"); |
207 function_fullname); | 182 OS::Print("Variable Descriptors for function '%s' {\n", function_fullname); |
208 const LocalVarDescriptors& var_descriptors = | 183 const LocalVarDescriptors& var_descriptors = |
209 LocalVarDescriptors::Handle(code.var_descriptors()); | 184 LocalVarDescriptors::Handle(code.var_descriptors()); |
210 intptr_t var_desc_length = | 185 intptr_t var_desc_length = |
211 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); | 186 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); |
212 String& var_name = String::Handle(); | 187 String& var_name = String::Handle(); |
213 for (intptr_t i = 0; i < var_desc_length; i++) { | 188 for (intptr_t i = 0; i < var_desc_length; i++) { |
214 var_name = var_descriptors.GetName(i); | 189 var_name = var_descriptors.GetName(i); |
215 intptr_t scope_id, begin_pos, end_pos; | 190 intptr_t scope_id, begin_pos, end_pos; |
216 var_descriptors.GetScopeInfo(i, &scope_id, &begin_pos, &end_pos); | 191 var_descriptors.GetScopeInfo(i, &scope_id, &begin_pos, &end_pos); |
217 intptr_t slot = var_descriptors.GetSlotIndex(i); | 192 intptr_t slot = var_descriptors.GetSlotIndex(i); |
218 OS::Print(" var %s scope %ld (valid %d-%d) offset %ld\n", | 193 OS::Print(" var %s scope %ld (valid %d-%d) offset %ld\n", |
219 var_name.ToCString(), scope_id, begin_pos, end_pos, slot); | 194 var_name.ToCString(), scope_id, begin_pos, end_pos, slot); |
220 } | 195 } |
221 OS::Print("}\n"); | 196 OS::Print("}\n"); |
222 OS::Print("Exception Handlers for function '%s' {\n", function_fullname); | 197 OS::Print("Exception Handlers for function '%s' {\n", function_fullname); |
223 const ExceptionHandlers& handlers = | 198 const ExceptionHandlers& handlers = |
224 ExceptionHandlers::Handle(code.exception_handlers()); | 199 ExceptionHandlers::Handle(code.exception_handlers()); |
225 OS::Print("%s", handlers.ToCString()); | 200 OS::Print("%s", handlers.ToCString()); |
226 OS::Print("}\n"); | 201 OS::Print("}\n"); |
227 } | 202 } |
228 } else { | 203 } |
229 // We got an error during compilation. | 204 |
230 error = isolate->object_store()->sticky_error(); | 205 |
231 isolate->object_store()->clear_sticky_error(); | 206 void Compiler::CompileFunction(const Function& function) { |
232 } | 207 CompileFunctionHelper(function, false); |
233 isolate->set_long_jump_base(base); | 208 } |
234 return error.raw(); | 209 |
235 } | 210 |
236 | 211 void Compiler::CompileOptimizedFunction(const Function& function) { |
237 | 212 CompileFunctionHelper(function, true); |
238 RawError* Compiler::CompileFunction(const Function& function) { | 213 } |
239 return CompileFunctionHelper(function, false); | 214 |
240 } | 215 |
241 | 216 void Compiler::CompileAllFunctions(const Class& cls) { |
242 | 217 Array& functions = Array::Handle(cls.functions()); |
243 RawError* Compiler::CompileOptimizedFunction(const Function& function) { | 218 Function& func = Function::Handle(); |
244 return CompileFunctionHelper(function, true); | 219 for (int i = 0; i < functions.Length(); i++) { |
245 } | 220 func ^= functions.At(i); |
246 | 221 ASSERT(!func.IsNull()); |
247 | 222 if (!func.HasCode() && !func.IsAbstract()) { |
248 RawError* Compiler::CompileAllFunctions(const Class& cls) { | 223 CompileFunction(func); |
249 Isolate* isolate = Isolate::Current(); | 224 } |
250 Error& error = Error::Handle(); | 225 } |
251 LongJump* base = isolate->long_jump_base(); | 226 } |
252 LongJump jump; | 227 |
253 isolate->set_long_jump_base(&jump); | 228 |
254 if (setjmp(*jump.Set()) == 0) { | 229 RawInstance* Compiler::ExecuteOnce(SequenceNode* fragment) { |
255 Array& functions = Array::Handle(cls.functions()); | 230 if (FLAG_trace_compiler) { |
256 Function& func = Function::Handle(); | 231 OS::Print("compiling expression: "); |
257 for (int i = 0; i < functions.Length(); i++) { | 232 AstPrinter::PrintNode(fragment); |
258 func ^= functions.At(i); | 233 } |
259 ASSERT(!func.IsNull()); | 234 |
260 if (!func.HasCode() && !func.IsAbstract()) { | 235 // Create a dummy function object for the code generator. |
261 const Error& error = Error::Handle(CompileFunction(func)); | 236 const char* kEvalConst = "eval_const"; |
262 if (!error.IsNull()) { | 237 const Function& func = Function::Handle(Function::New( |
263 return error.raw(); | 238 String::Handle(String::NewSymbol(kEvalConst)), |
264 } | 239 RawFunction::kConstImplicitGetter, |
265 } | 240 true, // static function. |
266 } | 241 false, // not const function. |
267 } else { | 242 fragment->token_index())); |
268 error = isolate->object_store()->sticky_error(); | 243 |
269 isolate->object_store()->clear_sticky_error(); | 244 func.set_result_type(Type::Handle(Type::DynamicType())); |
270 } | 245 func.set_num_fixed_parameters(0); |
271 isolate->set_long_jump_base(base); | 246 func.set_num_optional_parameters(0); |
272 return error.raw(); | 247 |
273 } | 248 // The function needs to be associated with a named Class: the interface |
274 | 249 // Function fits the bill. |
275 | 250 func.set_owner(Class::Handle( |
276 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { | 251 Type::Handle(Type::FunctionInterface()).type_class())); |
277 Isolate* isolate = Isolate::Current(); | 252 |
278 Object& result = Object::Handle(); | 253 // We compile the function here, even though InvokeStatic() below |
279 LongJump* base = isolate->long_jump_base(); | 254 // would compile func automatically. We are checking fewer invariants |
280 LongJump jump; | 255 // here. |
281 isolate->set_long_jump_base(&jump); | 256 ParsedFunction parsed_function(func); |
282 if (setjmp(*jump.Set()) == 0) { | 257 parsed_function.set_node_sequence(fragment); |
283 if (FLAG_trace_compiler) { | 258 parsed_function.set_default_parameter_values(Array::Handle()); |
284 OS::Print("compiling expression: "); | 259 |
285 AstPrinter::PrintNode(fragment); | 260 Assembler assembler; |
286 } | 261 CodeGenerator code_gen(&assembler, parsed_function); |
287 | 262 code_gen.GenerateCode(); |
288 // Create a dummy function object for the code generator. | 263 const Code& code = Code::Handle(Code::FinalizeCode(kEvalConst, &assembler)); |
289 const char* kEvalConst = "eval_const"; | 264 |
290 const Function& func = Function::Handle(Function::New( | 265 func.SetCode(code); |
291 String::Handle(String::NewSymbol(kEvalConst)), | 266 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table(); |
292 RawFunction::kConstImplicitGetter, | 267 ASSERT(code_index_table != NULL); |
293 true, // static function. | 268 code_index_table->AddFunction(func); |
294 false, // not const function. | 269 // TODO(hausner): We need a way to remove these one-time execution |
295 fragment->token_index())); | 270 // functions from the global code description (PC mapping) tables so |
296 | 271 // we don't pollute the system unnecessarily with stale data. |
297 func.set_result_type(Type::Handle(Type::DynamicType())); | 272 code_gen.FinalizePcDescriptors(code); |
298 func.set_num_fixed_parameters(0); | 273 code_gen.FinalizeExceptionHandlers(code); |
299 func.set_num_optional_parameters(0); | 274 |
300 | 275 GrowableArray<const Object*> arguments; // no arguments. |
301 // The function needs to be associated with a named Class: the interface | 276 const Array& kNoArgumentNames = Array::Handle(); |
302 // Function fits the bill. | 277 Instance& result = Instance::Handle( |
303 func.set_owner(Class::Handle( | 278 DartEntry::InvokeStatic(func, |
304 Type::Handle(Type::FunctionInterface()).type_class())); | 279 arguments, |
305 | 280 kNoArgumentNames)); |
306 // We compile the function here, even though InvokeStatic() below | 281 if (result.IsUnhandledException()) { |
307 // would compile func automatically. We are checking fewer invariants | 282 // TODO(srdjan): implement proper exit from compiler. |
308 // here. | 283 UNIMPLEMENTED(); |
309 ParsedFunction parsed_function(func); | 284 } |
310 parsed_function.set_node_sequence(fragment); | |
311 parsed_function.set_default_parameter_values(Array::Handle()); | |
312 | |
313 Assembler assembler; | |
314 CodeGenerator code_gen(&assembler, parsed_function); | |
315 code_gen.GenerateCode(); | |
316 const Code& code = Code::Handle(Code::FinalizeCode(kEvalConst, &assembler)); | |
317 | |
318 func.SetCode(code); | |
319 CodeIndexTable* code_index_table = isolate->code_index_table(); | |
320 ASSERT(code_index_table != NULL); | |
321 code_index_table->AddFunction(func); | |
322 // TODO(hausner): We need a way to remove these one-time execution | |
323 // functions from the global code description (PC mapping) tables so | |
324 // we don't pollute the system unnecessarily with stale data. | |
325 code_gen.FinalizePcDescriptors(code); | |
326 code_gen.FinalizeExceptionHandlers(code); | |
327 | |
328 GrowableArray<const Object*> arguments; // no arguments. | |
329 const Array& kNoArgumentNames = Array::Handle(); | |
330 result = DartEntry::InvokeStatic(func, | |
331 arguments, | |
332 kNoArgumentNames); | |
333 } else { | |
334 result = isolate->object_store()->sticky_error(); | |
335 isolate->object_store()->clear_sticky_error(); | |
336 } | |
337 isolate->set_long_jump_base(base); | |
338 return result.raw(); | 285 return result.raw(); |
339 } | 286 } |
340 | 287 |
341 | 288 |
342 } // namespace dart | 289 } // namespace dart |
OLD | NEW |