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

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

Issue 9169102: Add Dart_PropagateError. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Removed some unneeded includes Created 8 years, 11 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
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 = var_descriptors.Length();
211 String& var_name = String::Handle();
212 for (intptr_t i = 0; i < var_desc_length; i++) {
213 var_name = var_descriptors.GetName(i);
214 intptr_t scope_id, ignore;
215 var_descriptors.GetScopeInfo(i, &scope_id, &ignore, &ignore);
216 intptr_t slot = var_descriptors.GetSlotIndex(i);
217 OS::Print(" var %s scope %ld offset %ld\n",
218 var_name.ToCString(), scope_id, slot);
219 }
220 OS::Print("}\n");
221 OS::Print("Exception Handlers for function '%s' {\n", function_fullname);
222 const ExceptionHandlers& handlers =
223 ExceptionHandlers::Handle(code.exception_handlers());
224 OS::Print("%s", handlers.ToCString());
225 OS::Print("}\n");
226 }
227 } else {
228 // We got an error during compilation.
229 error = isolate->object_store()->sticky_error();
230 isolate->object_store()->clear_sticky_error();
231 }
232 isolate->set_long_jump_base(base);
233 return error.raw();
234 }
235
236
237 RawError* Compiler::CompileFunction(const Function& function) {
238 return CompileFunctionHelper(function, false);
239 }
240
241
242 RawError* Compiler::CompileOptimizedFunction(const Function& function) {
243 return CompileFunctionHelper(function, true);
244 }
245
246
247 RawError* Compiler::CompileAllFunctions(const Class& cls) {
248 Isolate* isolate = Isolate::Current();
249 Error& error = Error::Handle();
250 LongJump* base = isolate->long_jump_base();
251 LongJump jump;
252 isolate->set_long_jump_base(&jump);
253 if (setjmp(*jump.Set()) == 0) {
254 Array& functions = Array::Handle(cls.functions());
255 Function& func = Function::Handle();
256 for (int i = 0; i < functions.Length(); i++) {
257 func ^= functions.At(i);
258 ASSERT(!func.IsNull());
259 if (!func.HasCode() && !func.IsAbstract()) {
260 const Error& error = Error::Handle(CompileFunction(func));
261 if (!error.IsNull()) {
262 return error.raw();
263 }
264 }
265 }
266 } else {
267 error = isolate->object_store()->sticky_error();
268 isolate->object_store()->clear_sticky_error();
269 }
270 isolate->set_long_jump_base(base);
271 return error.raw();
272 }
273
274
275 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
276 Isolate* isolate = Isolate::Current();
277 Object& result = Object::Handle();
278 LongJump* base = isolate->long_jump_base();
279 LongJump jump;
280 isolate->set_long_jump_base(&jump);
281 if (setjmp(*jump.Set()) == 0) {
282 if (FLAG_trace_compiler) {
283 OS::Print("compiling expression: ");
284 AstPrinter::PrintNode(fragment);
285 }
286
287 // Create a dummy function object for the code generator.
288 const char* kEvalConst = "eval_const";
289 const Function& func = Function::Handle(Function::New(
290 String::Handle(String::NewSymbol(kEvalConst)),
291 RawFunction::kConstImplicitGetter,
292 true, // static function.
293 false, // not const function.
294 fragment->token_index()));
295
296 func.set_result_type(Type::Handle(Type::DynamicType()));
297 func.set_num_fixed_parameters(0);
298 func.set_num_optional_parameters(0);
299
300 // The function needs to be associated with a named Class: the interface
301 // Function fits the bill.
302 func.set_owner(Class::Handle(
303 Type::Handle(Type::FunctionInterface()).type_class()));
304
305 // We compile the function here, even though InvokeStatic() below
306 // would compile func automatically. We are checking fewer invariants
307 // here.
308 ParsedFunction parsed_function(func);
309 parsed_function.set_node_sequence(fragment);
310 parsed_function.set_default_parameter_values(Array::Handle());
311
312 Assembler assembler;
313 CodeGenerator code_gen(&assembler, parsed_function);
106 code_gen.GenerateCode(); 314 code_gen.GenerateCode();
107 Code& code = Code::Handle( 315 const Code& code = Code::Handle(Code::FinalizeCode(kEvalConst, &assembler));
108 Code::FinalizeCode(function_fullname, &assembler)); 316
109 code.set_is_optimized(true); 317 func.SetCode(code);
318 CodeIndexTable* code_index_table = isolate->code_index_table();
319 ASSERT(code_index_table != NULL);
320 code_index_table->AddFunction(func);
321 // TODO(hausner): We need a way to remove these one-time execution
322 // functions from the global code description (PC mapping) tables so
323 // we don't pollute the system unnecessarily with stale data.
110 code_gen.FinalizePcDescriptors(code); 324 code_gen.FinalizePcDescriptors(code);
111 code_gen.FinalizeExceptionHandlers(code); 325 code_gen.FinalizeExceptionHandlers(code);
112 function.SetCode(code); 326
113 code_index_table->AddFunction(function); 327 GrowableArray<const Object*> arguments; // no arguments.
114 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); 328 const Array& kNoArgumentNames = Array::Handle();
115 if (FLAG_trace_compiler) { 329 result = DartEntry::InvokeStatic(func,
116 OS::Print("--> patching entry 0x%x\n", 330 arguments,
117 Code::Handle(function.unoptimized_code()).EntryPoint()); 331 kNoArgumentNames);
118 } 332 } else {
119 } else { 333 result = isolate->object_store()->sticky_error();
120 // Unoptimized code. 334 isolate->object_store()->clear_sticky_error();
121 if (Code::Handle(function.unoptimized_code()).IsNull()) { 335 }
122 ASSERT(Code::Handle(function.code()).IsNull()); 336 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 = var_descriptors.Length();
186 String& var_name = String::Handle();
187 for (intptr_t i = 0; i < var_desc_length; i++) {
188 var_name = var_descriptors.GetName(i);
189 intptr_t scope_id, ignore;
190 var_descriptors.GetScopeInfo(i, &scope_id, &ignore, &ignore);
191 intptr_t slot = var_descriptors.GetSlotIndex(i);
192 OS::Print(" var %s scope %ld offset %ld\n",
193 var_name.ToCString(), scope_id, slot);
194 }
195 OS::Print("}\n");
196 OS::Print("Exception Handlers for function '%s' {\n", function_fullname);
197 const ExceptionHandlers& handlers =
198 ExceptionHandlers::Handle(code.exception_handlers());
199 OS::Print("%s", handlers.ToCString());
200 OS::Print("}\n");
201 }
202 }
203
204
205 void Compiler::CompileFunction(const Function& function) {
206 CompileFunctionHelper(function, false);
207 }
208
209
210 void Compiler::CompileOptimizedFunction(const Function& function) {
211 CompileFunctionHelper(function, true);
212 }
213
214
215 void Compiler::CompileAllFunctions(const Class& cls) {
216 Array& functions = Array::Handle(cls.functions());
217 Function& func = Function::Handle();
218 for (int i = 0; i < functions.Length(); i++) {
219 func ^= functions.At(i);
220 ASSERT(!func.IsNull());
221 if (!func.HasCode() && !func.IsAbstract()) {
222 CompileFunction(func);
223 }
224 }
225 }
226
227
228 RawInstance* Compiler::ExecuteOnce(SequenceNode* fragment) {
229 if (FLAG_trace_compiler) {
230 OS::Print("compiling expression: ");
231 AstPrinter::PrintNode(fragment);
232 }
233
234 // Create a dummy function object for the code generator.
235 const char* kEvalConst = "eval_const";
236 const Function& func = Function::Handle(Function::New(
237 String::Handle(String::NewSymbol(kEvalConst)),
238 RawFunction::kConstImplicitGetter,
239 true, // static function.
240 false, // not const function.
241 fragment->token_index()));
242
243 func.set_result_type(Type::Handle(Type::DynamicType()));
244 func.set_num_fixed_parameters(0);
245 func.set_num_optional_parameters(0);
246
247 // The function needs to be associated with a named Class: the interface
248 // Function fits the bill.
249 func.set_owner(Class::Handle(
250 Type::Handle(Type::FunctionInterface()).type_class()));
251
252 // We compile the function here, even though InvokeStatic() below
253 // would compile func automatically. We are checking fewer invariants
254 // here.
255 ParsedFunction parsed_function(func);
256 parsed_function.set_node_sequence(fragment);
257 parsed_function.set_default_parameter_values(Array::Handle());
258
259 Assembler assembler;
260 CodeGenerator code_gen(&assembler, parsed_function);
261 code_gen.GenerateCode();
262 const Code& code = Code::Handle(Code::FinalizeCode(kEvalConst, &assembler));
263
264 func.SetCode(code);
265 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table();
266 ASSERT(code_index_table != NULL);
267 code_index_table->AddFunction(func);
268 // TODO(hausner): We need a way to remove these one-time execution
269 // functions from the global code description (PC mapping) tables so
270 // we don't pollute the system unnecessarily with stale data.
271 code_gen.FinalizePcDescriptors(code);
272 code_gen.FinalizeExceptionHandlers(code);
273
274 GrowableArray<const Object*> arguments; // no arguments.
275 const Array& kNoArgumentNames = Array::Handle();
276 Instance& result = Instance::Handle(
277 DartEntry::InvokeStatic(func,
278 arguments,
279 kNoArgumentNames));
280 if (result.IsUnhandledException()) {
281 // TODO(srdjan): implement proper exit from compiler.
282 UNIMPLEMENTED();
283 }
284 return result.raw(); 337 return result.raw();
285 } 338 }
286 339
287 340
288 } // namespace dart 341 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698