Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: runtime/vm/compiler.cc

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

Powered by Google App Engine
This is Rietveld 408576698