OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "vm/resolver.h" | 25 #include "vm/resolver.h" |
26 #include "vm/scopes.h" | 26 #include "vm/scopes.h" |
27 #include "vm/stack_frame.h" | 27 #include "vm/stack_frame.h" |
28 #include "vm/stub_code.h" | 28 #include "vm/stub_code.h" |
29 #include "vm/symbols.h" | 29 #include "vm/symbols.h" |
30 #include "vm/token.h" | 30 #include "vm/token.h" |
31 #include "vm/zone.h" | 31 #include "vm/zone.h" |
32 | 32 |
33 namespace dart { | 33 namespace dart { |
34 | 34 |
35 DEFINE_FLAG(bool, eliminate_type_checks, true, | 35 DEFINE_FLAG(bool, |
| 36 eliminate_type_checks, |
| 37 true, |
36 "Eliminate type checks when allowed by static type analysis."); | 38 "Eliminate type checks when allowed by static type analysis."); |
37 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); | 39 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); |
38 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); | 40 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); |
39 DEFINE_FLAG(bool, trace_type_check_elimination, false, | 41 DEFINE_FLAG(bool, |
| 42 trace_type_check_elimination, |
| 43 false, |
40 "Trace type check elimination at compile time."); | 44 "Trace type check elimination at compile time."); |
41 | 45 |
42 DECLARE_FLAG(bool, profile_vm); | 46 DECLARE_FLAG(bool, profile_vm); |
43 DECLARE_FLAG(bool, support_externalizable_strings); | 47 DECLARE_FLAG(bool, support_externalizable_strings); |
44 | 48 |
45 // Quick access to the locally defined zone() method. | 49 // Quick access to the locally defined zone() method. |
46 #define Z (zone()) | 50 #define Z (zone()) |
47 | 51 |
48 // Quick access to the locally defined thread() method. | 52 // Quick access to the locally defined thread() method. |
49 #define T (thread()) | 53 #define T (thread()) |
50 | 54 |
51 // Quick synthetic token position. | 55 // Quick synthetic token position. |
52 #define ST(token_pos) ((token_pos).ToSynthetic()) | 56 #define ST(token_pos) ((token_pos).ToSynthetic()) |
53 | 57 |
54 // TODO(srdjan): Allow compiler to add constants as they are encountered in | 58 // TODO(srdjan): Allow compiler to add constants as they are encountered in |
55 // the compilation. | 59 // the compilation. |
56 const double kCommonDoubleConstants[] = | 60 const double kCommonDoubleConstants[] = { |
57 {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0, | 61 -1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0, 10.0, 20.0, 30.0, 64.0, |
58 10.0, 20.0, 30.0, 64.0, 255.0, NAN, | 62 255.0, NAN, |
59 // From dart:math | 63 // From dart:math |
60 2.718281828459045, 2.302585092994046, 0.6931471805599453, | 64 2.718281828459045, 2.302585092994046, 0.6931471805599453, |
61 1.4426950408889634, 0.4342944819032518, 3.1415926535897932, | 65 1.4426950408889634, 0.4342944819032518, 3.1415926535897932, |
62 0.7071067811865476, 1.4142135623730951}; | 66 0.7071067811865476, 1.4142135623730951}; |
63 | 67 |
64 uword FlowGraphBuilder::FindDoubleConstant(double value) { | 68 uword FlowGraphBuilder::FindDoubleConstant(double value) { |
65 intptr_t len = sizeof(kCommonDoubleConstants) / sizeof(double); // NOLINT | 69 intptr_t len = sizeof(kCommonDoubleConstants) / sizeof(double); // NOLINT |
66 for (intptr_t i = 0; i < len; i++) { | 70 for (intptr_t i = 0; i < len; i++) { |
67 if (Utils::DoublesBitEqual(value, kCommonDoubleConstants[i])) { | 71 if (Utils::DoublesBitEqual(value, kCommonDoubleConstants[i])) { |
68 return reinterpret_cast<uword>(&kCommonDoubleConstants[i]); | 72 return reinterpret_cast<uword>(&kCommonDoubleConstants[i]); |
69 } | 73 } |
70 } | 74 } |
71 return 0; | 75 return 0; |
72 } | 76 } |
73 | 77 |
74 | 78 |
75 #define RECOGNIZE_FACTORY(test_factory_symbol, cid, fp) \ | 79 #define RECOGNIZE_FACTORY(test_factory_symbol, cid, fp) \ |
76 { Symbols::k##test_factory_symbol##Id, cid, \ | 80 {Symbols::k##test_factory_symbol##Id, cid, fp, \ |
77 fp, #test_factory_symbol ", " #cid }, | 81 #test_factory_symbol ", " #cid}, // NOLINT |
78 | 82 |
79 static struct { | 83 static struct { |
80 intptr_t symbold_id; | 84 intptr_t symbold_id; |
81 intptr_t cid; | 85 intptr_t cid; |
82 intptr_t finger_print; | 86 intptr_t finger_print; |
83 const char* name; | 87 const char* name; |
84 } factory_recognizer_list[] = { | 88 } factory_recognizer_list[] = {RECOGNIZED_LIST_FACTORY_LIST(RECOGNIZE_FACTORY){ |
85 RECOGNIZED_LIST_FACTORY_LIST(RECOGNIZE_FACTORY) | 89 Symbols::kIllegal, -1, -1, NULL}}; |
86 { Symbols::kIllegal, -1, -1, NULL } | |
87 }; | |
88 | 90 |
89 #undef RECOGNIZE_FACTORY | 91 #undef RECOGNIZE_FACTORY |
90 | 92 |
91 intptr_t FactoryRecognizer::ResultCid(const Function& factory) { | 93 intptr_t FactoryRecognizer::ResultCid(const Function& factory) { |
92 ASSERT(factory.IsFactory()); | 94 ASSERT(factory.IsFactory()); |
93 const Class& function_class = Class::Handle(factory.Owner()); | 95 const Class& function_class = Class::Handle(factory.Owner()); |
94 const Library& lib = Library::Handle(function_class.library()); | 96 const Library& lib = Library::Handle(function_class.library()); |
95 ASSERT((lib.raw() == Library::CoreLibrary()) || | 97 ASSERT((lib.raw() == Library::CoreLibrary()) || |
96 (lib.raw() == Library::TypedDataLibrary())); | 98 (lib.raw() == Library::TypedDataLibrary())); |
97 const String& factory_name = String::Handle(factory.name()); | 99 const String& factory_name = String::Handle(factory.name()); |
98 for (intptr_t i = 0; | 100 for (intptr_t i = 0; |
99 factory_recognizer_list[i].symbold_id != Symbols::kIllegal; | 101 factory_recognizer_list[i].symbold_id != Symbols::kIllegal; i++) { |
100 i++) { | |
101 if (String::EqualsIgnoringPrivateKey( | 102 if (String::EqualsIgnoringPrivateKey( |
102 factory_name, | 103 factory_name, |
103 Symbols::Symbol(factory_recognizer_list[i].symbold_id))) { | 104 Symbols::Symbol(factory_recognizer_list[i].symbold_id))) { |
104 return factory_recognizer_list[i].cid; | 105 return factory_recognizer_list[i].cid; |
105 } | 106 } |
106 } | 107 } |
107 return kDynamicCid; | 108 return kDynamicCid; |
108 } | 109 } |
109 | 110 |
110 | 111 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 | 167 |
167 | 168 |
168 intptr_t FlowGraphBuilder::context_level() const { | 169 intptr_t FlowGraphBuilder::context_level() const { |
169 return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel(); | 170 return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel(); |
170 } | 171 } |
171 | 172 |
172 | 173 |
173 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { | 174 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { |
174 if (label != label_) return NULL; | 175 if (label != label_) return NULL; |
175 if (break_target_ == NULL) { | 176 if (break_target_ == NULL) { |
176 break_target_ = | 177 break_target_ = new (owner()->zone()) |
177 new(owner()->zone()) JoinEntryInstr(owner()->AllocateBlockId(), | 178 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); |
178 try_index()); | |
179 } | 179 } |
180 return break_target_; | 180 return break_target_; |
181 } | 181 } |
182 | 182 |
183 | 183 |
184 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { | 184 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { |
185 return NULL; | 185 return NULL; |
186 } | 186 } |
187 | 187 |
188 | 188 |
189 // A nested statement that has its own context level. | 189 // A nested statement that has its own context level. |
190 class NestedBlock : public NestedStatement { | 190 class NestedBlock : public NestedStatement { |
191 public: | 191 public: |
192 NestedBlock(FlowGraphBuilder* owner, SequenceNode* node) | 192 NestedBlock(FlowGraphBuilder* owner, SequenceNode* node) |
193 : NestedStatement(owner, node->label()), scope_(node->scope()) {} | 193 : NestedStatement(owner, node->label()), scope_(node->scope()) {} |
194 | 194 |
195 virtual intptr_t ContextLevel() const; | 195 virtual intptr_t ContextLevel() const; |
196 | 196 |
197 private: | 197 private: |
198 LocalScope* scope_; | 198 LocalScope* scope_; |
199 }; | 199 }; |
200 | 200 |
201 | 201 |
202 intptr_t NestedBlock::ContextLevel() const { | 202 intptr_t NestedBlock::ContextLevel() const { |
203 return ((scope_ == NULL) || (scope_->num_context_variables() == 0)) | 203 return ((scope_ == NULL) || (scope_->num_context_variables() == 0)) |
204 ? NestedStatement::ContextLevel() | 204 ? NestedStatement::ContextLevel() |
205 : scope_->context_level(); | 205 : scope_->context_level(); |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 // A nested statement reflecting a context level adjustment. | 209 // A nested statement reflecting a context level adjustment. |
210 class NestedContextAdjustment : public NestedStatement { | 210 class NestedContextAdjustment : public NestedStatement { |
211 public: | 211 public: |
212 NestedContextAdjustment(FlowGraphBuilder* owner, intptr_t context_level) | 212 NestedContextAdjustment(FlowGraphBuilder* owner, intptr_t context_level) |
213 : NestedStatement(owner, NULL), context_level_(context_level) { } | 213 : NestedStatement(owner, NULL), context_level_(context_level) {} |
214 | 214 |
215 virtual intptr_t ContextLevel() const { return context_level_; } | 215 virtual intptr_t ContextLevel() const { return context_level_; } |
216 | 216 |
217 virtual void AdjustContextLevel(intptr_t context_level) { | 217 virtual void AdjustContextLevel(intptr_t context_level) { |
218 ASSERT(context_level <= context_level_); | 218 ASSERT(context_level <= context_level_); |
219 context_level_ = context_level; | 219 context_level_ = context_level; |
220 } | 220 } |
221 | 221 |
222 private: | 222 private: |
223 intptr_t context_level_; | 223 intptr_t context_level_; |
224 }; | 224 }; |
225 | 225 |
226 | 226 |
227 // A nested statement that can be the target of a continue as well as a | 227 // A nested statement that can be the target of a continue as well as a |
228 // break. | 228 // break. |
229 class NestedLoop : public NestedStatement { | 229 class NestedLoop : public NestedStatement { |
230 public: | 230 public: |
231 NestedLoop(FlowGraphBuilder* owner, SourceLabel* label) | 231 NestedLoop(FlowGraphBuilder* owner, SourceLabel* label) |
232 : NestedStatement(owner, label), continue_target_(NULL) { | 232 : NestedStatement(owner, label), continue_target_(NULL) { |
233 owner->IncrementLoopDepth(); | 233 owner->IncrementLoopDepth(); |
234 } | 234 } |
235 | 235 |
236 virtual ~NestedLoop() { | 236 virtual ~NestedLoop() { owner()->DecrementLoopDepth(); } |
237 owner()->DecrementLoopDepth(); | |
238 } | |
239 | 237 |
240 JoinEntryInstr* continue_target() const { return continue_target_; } | 238 JoinEntryInstr* continue_target() const { return continue_target_; } |
241 | 239 |
242 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); | 240 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); |
243 | 241 |
244 private: | 242 private: |
245 JoinEntryInstr* continue_target_; | 243 JoinEntryInstr* continue_target_; |
246 }; | 244 }; |
247 | 245 |
248 | 246 |
249 JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) { | 247 JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) { |
250 if (label != this->label()) return NULL; | 248 if (label != this->label()) return NULL; |
251 if (continue_target_ == NULL) { | 249 if (continue_target_ == NULL) { |
252 continue_target_ = | 250 continue_target_ = new (owner()->zone()) |
253 new(owner()->zone()) JoinEntryInstr(owner()->AllocateBlockId(), | 251 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); |
254 try_index()); | |
255 } | 252 } |
256 return continue_target_; | 253 return continue_target_; |
257 } | 254 } |
258 | 255 |
259 | 256 |
260 // A nested switch which can be the target of a break if labeled, and whose | 257 // A nested switch which can be the target of a break if labeled, and whose |
261 // cases can be the targets of continues. | 258 // cases can be the targets of continues. |
262 class NestedSwitch : public NestedStatement { | 259 class NestedSwitch : public NestedStatement { |
263 public: | 260 public: |
264 NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node); | 261 NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node); |
(...skipping 21 matching lines...) Expand all Loading... |
286 } | 283 } |
287 | 284 |
288 | 285 |
289 JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) { | 286 JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) { |
290 // Allocate a join for a case clause that matches the label. This block | 287 // Allocate a join for a case clause that matches the label. This block |
291 // is not necessarily targeted by a continue, but we always use a join in | 288 // is not necessarily targeted by a continue, but we always use a join in |
292 // the graph anyway. | 289 // the graph anyway. |
293 for (intptr_t i = 0; i < case_labels_.length(); ++i) { | 290 for (intptr_t i = 0; i < case_labels_.length(); ++i) { |
294 if (label != case_labels_[i]) continue; | 291 if (label != case_labels_[i]) continue; |
295 if (case_targets_[i] == NULL) { | 292 if (case_targets_[i] == NULL) { |
296 case_targets_[i] = | 293 case_targets_[i] = new (owner()->zone()) |
297 new(owner()->zone()) JoinEntryInstr(owner()->AllocateBlockId(), | 294 JoinEntryInstr(owner()->AllocateBlockId(), try_index()); |
298 try_index()); | |
299 } | 295 } |
300 return case_targets_[i]; | 296 return case_targets_[i]; |
301 } | 297 } |
302 return NULL; | 298 return NULL; |
303 } | 299 } |
304 | 300 |
305 | 301 |
306 FlowGraphBuilder::FlowGraphBuilder( | 302 FlowGraphBuilder::FlowGraphBuilder( |
307 const ParsedFunction& parsed_function, | 303 const ParsedFunction& parsed_function, |
308 const ZoneGrowableArray<const ICData*>& ic_data_array, | 304 const ZoneGrowableArray<const ICData*>& ic_data_array, |
309 InlineExitCollector* exit_collector, | 305 InlineExitCollector* exit_collector, |
310 intptr_t osr_id) : | 306 intptr_t osr_id) |
311 parsed_function_(parsed_function), | 307 : parsed_function_(parsed_function), |
312 ic_data_array_(ic_data_array), | 308 ic_data_array_(ic_data_array), |
313 num_copied_params_(parsed_function.num_copied_params()), | 309 num_copied_params_(parsed_function.num_copied_params()), |
314 // All parameters are copied if any parameter is. | 310 // All parameters are copied if any parameter is. |
315 num_non_copied_params_((num_copied_params_ == 0) | 311 num_non_copied_params_( |
316 ? parsed_function.function().num_fixed_parameters() | 312 (num_copied_params_ == 0) |
317 : 0), | 313 ? parsed_function.function().num_fixed_parameters() |
318 num_stack_locals_(parsed_function.num_stack_locals()), | 314 : 0), |
319 exit_collector_(exit_collector), | 315 num_stack_locals_(parsed_function.num_stack_locals()), |
320 last_used_block_id_(0), // 0 is used for the graph entry. | 316 exit_collector_(exit_collector), |
321 try_index_(CatchClauseNode::kInvalidTryIndex), | 317 last_used_block_id_(0), // 0 is used for the graph entry. |
322 catch_try_index_(CatchClauseNode::kInvalidTryIndex), | 318 try_index_(CatchClauseNode::kInvalidTryIndex), |
323 loop_depth_(0), | 319 catch_try_index_(CatchClauseNode::kInvalidTryIndex), |
324 graph_entry_(NULL), | 320 loop_depth_(0), |
325 temp_count_(0), | 321 graph_entry_(NULL), |
326 args_pushed_(0), | 322 temp_count_(0), |
327 nesting_stack_(NULL), | 323 args_pushed_(0), |
328 osr_id_(osr_id), | 324 nesting_stack_(NULL), |
329 jump_count_(0), | 325 osr_id_(osr_id), |
330 await_joins_(new(Z) ZoneGrowableArray<JoinEntryInstr*>()) { } | 326 jump_count_(0), |
| 327 await_joins_(new (Z) ZoneGrowableArray<JoinEntryInstr*>()) {} |
331 | 328 |
332 | 329 |
333 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { | 330 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
334 graph_entry_->AddCatchEntry(entry); | 331 graph_entry_->AddCatchEntry(entry); |
335 } | 332 } |
336 | 333 |
337 | 334 |
338 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { | 335 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { |
339 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); | 336 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); |
340 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); | 337 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); |
341 ASSERT(callee_graph->max_virtual_register_number() > | 338 ASSERT(callee_graph->max_virtual_register_number() > |
342 caller_graph_->max_virtual_register_number()); | 339 caller_graph_->max_virtual_register_number()); |
343 | 340 |
344 // Adjust the caller's maximum block id and current SSA temp index. | 341 // Adjust the caller's maximum block id and current SSA temp index. |
345 caller_graph_->set_max_block_id(callee_graph->max_block_id()); | 342 caller_graph_->set_max_block_id(callee_graph->max_block_id()); |
346 caller_graph_->set_current_ssa_temp_index( | 343 caller_graph_->set_current_ssa_temp_index( |
347 callee_graph->max_virtual_register_number()); | 344 callee_graph->max_virtual_register_number()); |
348 | 345 |
349 // Attach the outer environment on each instruction in the callee graph. | 346 // Attach the outer environment on each instruction in the callee graph. |
350 ASSERT(call_->env() != NULL); | 347 ASSERT(call_->env() != NULL); |
351 // Scale the edge weights by the call count for the inlined function. | 348 // Scale the edge weights by the call count for the inlined function. |
352 double scale_factor = static_cast<double>(call_->CallCount()) | 349 double scale_factor = |
353 / static_cast<double>(caller_graph_->graph_entry()->entry_count()); | 350 static_cast<double>(call_->CallCount()) / |
| 351 static_cast<double>(caller_graph_->graph_entry()->entry_count()); |
354 for (BlockIterator block_it = callee_graph->postorder_iterator(); | 352 for (BlockIterator block_it = callee_graph->postorder_iterator(); |
355 !block_it.Done(); | 353 !block_it.Done(); block_it.Advance()) { |
356 block_it.Advance()) { | |
357 BlockEntryInstr* block = block_it.Current(); | 354 BlockEntryInstr* block = block_it.Current(); |
358 if (block->IsTargetEntry()) { | 355 if (block->IsTargetEntry()) { |
359 block->AsTargetEntry()->adjust_edge_weight(scale_factor); | 356 block->AsTargetEntry()->adjust_edge_weight(scale_factor); |
360 } | 357 } |
361 Instruction* instr = block; | 358 Instruction* instr = block; |
362 if (block->env() != NULL) { | 359 if (block->env() != NULL) { |
363 call_->env()->DeepCopyToOuter(callee_graph->zone(), block); | 360 call_->env()->DeepCopyToOuter(callee_graph->zone(), block); |
364 } | 361 } |
365 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 362 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
366 instr = it.Current(); | 363 instr = it.Current(); |
367 // TODO(zerny): Avoid creating unnecessary environments. Note that some | 364 // TODO(zerny): Avoid creating unnecessary environments. Note that some |
368 // optimizations need deoptimization info for non-deoptable instructions, | 365 // optimizations need deoptimization info for non-deoptable instructions, |
369 // eg, LICM on GOTOs. | 366 // eg, LICM on GOTOs. |
370 if (instr->env() != NULL) { | 367 if (instr->env() != NULL) { |
371 call_->env()->DeepCopyToOuter(callee_graph->zone(), instr); | 368 call_->env()->DeepCopyToOuter(callee_graph->zone(), instr); |
372 } | 369 } |
373 } | 370 } |
374 if (instr->IsGoto()) { | 371 if (instr->IsGoto()) { |
375 instr->AsGoto()->adjust_edge_weight(scale_factor); | 372 instr->AsGoto()->adjust_edge_weight(scale_factor); |
376 } | 373 } |
377 } | 374 } |
378 | 375 |
379 RemoveUnreachableExits(callee_graph); | 376 RemoveUnreachableExits(callee_graph); |
380 } | 377 } |
381 | 378 |
382 | 379 |
383 void InlineExitCollector::AddExit(ReturnInstr* exit) { | 380 void InlineExitCollector::AddExit(ReturnInstr* exit) { |
384 Data data = { NULL, exit }; | 381 Data data = {NULL, exit}; |
385 exits_.Add(data); | 382 exits_.Add(data); |
386 } | 383 } |
387 | 384 |
388 | 385 |
389 void InlineExitCollector::Union(const InlineExitCollector* other) { | 386 void InlineExitCollector::Union(const InlineExitCollector* other) { |
390 // It doesn't make sense to combine different calls or calls from | 387 // It doesn't make sense to combine different calls or calls from |
391 // different graphs. | 388 // different graphs. |
392 ASSERT(caller_graph_ == other->caller_graph_); | 389 ASSERT(caller_graph_ == other->caller_graph_); |
393 ASSERT(call_ == other->call_); | 390 ASSERT(call_ == other->call_); |
394 exits_.AddArray(other->exits_); | 391 exits_.AddArray(other->exits_); |
395 } | 392 } |
396 | 393 |
397 | 394 |
398 int InlineExitCollector::LowestBlockIdFirst(const Data* a, const Data* b) { | 395 int InlineExitCollector::LowestBlockIdFirst(const Data* a, const Data* b) { |
399 return (a->exit_block->block_id() - b->exit_block->block_id()); | 396 return (a->exit_block->block_id() - b->exit_block->block_id()); |
400 } | 397 } |
401 | 398 |
402 | 399 |
403 void InlineExitCollector::RemoveUnreachableExits(FlowGraph* callee_graph) { | 400 void InlineExitCollector::RemoveUnreachableExits(FlowGraph* callee_graph) { |
404 const GrowableArray<BlockEntryInstr*>& postorder = callee_graph->postorder(); | 401 const GrowableArray<BlockEntryInstr*>& postorder = callee_graph->postorder(); |
405 int j = 0; | 402 int j = 0; |
406 for (int i = 0; i < exits_.length(); ++i) { | 403 for (int i = 0; i < exits_.length(); ++i) { |
407 BlockEntryInstr* block = exits_[i].exit_return->GetBlock(); | 404 BlockEntryInstr* block = exits_[i].exit_return->GetBlock(); |
408 if ((block != NULL) && | 405 if ((block != NULL) && (0 <= block->postorder_number()) && |
409 (0 <= block->postorder_number()) && | |
410 (block->postorder_number() < postorder.length()) && | 406 (block->postorder_number() < postorder.length()) && |
411 (postorder[block->postorder_number()] == block)) { | 407 (postorder[block->postorder_number()] == block)) { |
412 if (i != j) { | 408 if (i != j) { |
413 exits_[j] = exits_[i]; | 409 exits_[j] = exits_[i]; |
414 } | 410 } |
415 j++; | 411 j++; |
416 } | 412 } |
417 } | 413 } |
418 exits_.TruncateTo(j); | 414 exits_.TruncateTo(j); |
419 } | 415 } |
(...skipping 19 matching lines...) Expand all Loading... |
439 if (num_exits == 1) { | 435 if (num_exits == 1) { |
440 ReturnAt(0)->UnuseAllInputs(); | 436 ReturnAt(0)->UnuseAllInputs(); |
441 *exit_block = ExitBlockAt(0); | 437 *exit_block = ExitBlockAt(0); |
442 *last_instruction = LastInstructionAt(0); | 438 *last_instruction = LastInstructionAt(0); |
443 return call_->HasUses() ? ValueAt(0)->definition() : NULL; | 439 return call_->HasUses() ? ValueAt(0)->definition() : NULL; |
444 } else { | 440 } else { |
445 ASSERT(num_exits > 1); | 441 ASSERT(num_exits > 1); |
446 // Create a join of the returns. | 442 // Create a join of the returns. |
447 intptr_t join_id = caller_graph_->max_block_id() + 1; | 443 intptr_t join_id = caller_graph_->max_block_id() + 1; |
448 caller_graph_->set_max_block_id(join_id); | 444 caller_graph_->set_max_block_id(join_id); |
449 JoinEntryInstr* join = | 445 JoinEntryInstr* join = new (Z) JoinEntryInstr(join_id, try_index); |
450 new(Z) JoinEntryInstr(join_id, try_index); | |
451 | 446 |
452 // The dominator set of the join is the intersection of the dominator | 447 // The dominator set of the join is the intersection of the dominator |
453 // sets of all the predecessors. If we keep the dominator sets ordered | 448 // sets of all the predecessors. If we keep the dominator sets ordered |
454 // by height in the dominator tree, we can also get the immediate | 449 // by height in the dominator tree, we can also get the immediate |
455 // dominator of the join node from the intersection. | 450 // dominator of the join node from the intersection. |
456 // | 451 // |
457 // block_dominators is the dominator set for each block, ordered from | 452 // block_dominators is the dominator set for each block, ordered from |
458 // the immediate dominator to the root of the dominator tree. This is | 453 // the immediate dominator to the root of the dominator tree. This is |
459 // the order we collect them in (adding at the end). | 454 // the order we collect them in (adding at the end). |
460 // | 455 // |
461 // join_dominators is the join's dominators ordered from the root of the | 456 // join_dominators is the join's dominators ordered from the root of the |
462 // dominator tree to the immediate dominator. This order supports | 457 // dominator tree to the immediate dominator. This order supports |
463 // removing during intersection by truncating the list. | 458 // removing during intersection by truncating the list. |
464 GrowableArray<BlockEntryInstr*> block_dominators; | 459 GrowableArray<BlockEntryInstr*> block_dominators; |
465 GrowableArray<BlockEntryInstr*> join_dominators; | 460 GrowableArray<BlockEntryInstr*> join_dominators; |
466 for (intptr_t i = 0; i < num_exits; ++i) { | 461 for (intptr_t i = 0; i < num_exits; ++i) { |
467 // Add the control-flow edge. | 462 // Add the control-flow edge. |
468 GotoInstr* goto_instr = new(Z) GotoInstr(join); | 463 GotoInstr* goto_instr = new (Z) GotoInstr(join); |
469 goto_instr->InheritDeoptTarget(zone(), ReturnAt(i)); | 464 goto_instr->InheritDeoptTarget(zone(), ReturnAt(i)); |
470 LastInstructionAt(i)->LinkTo(goto_instr); | 465 LastInstructionAt(i)->LinkTo(goto_instr); |
471 ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next()); | 466 ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next()); |
472 join->predecessors_.Add(ExitBlockAt(i)); | 467 join->predecessors_.Add(ExitBlockAt(i)); |
473 | 468 |
474 // Collect the block's dominators. | 469 // Collect the block's dominators. |
475 block_dominators.Clear(); | 470 block_dominators.Clear(); |
476 BlockEntryInstr* dominator = ExitBlockAt(i)->dominator(); | 471 BlockEntryInstr* dominator = ExitBlockAt(i)->dominator(); |
477 while (dominator != NULL) { | 472 while (dominator != NULL) { |
478 block_dominators.Add(dominator); | 473 block_dominators.Add(dominator); |
(...skipping 25 matching lines...) Expand all Loading... |
504 } | 499 } |
505 // The immediate dominator of the join is the last one in the ordered | 500 // The immediate dominator of the join is the last one in the ordered |
506 // intersection. | 501 // intersection. |
507 join_dominators.Last()->AddDominatedBlock(join); | 502 join_dominators.Last()->AddDominatedBlock(join); |
508 *exit_block = join; | 503 *exit_block = join; |
509 *last_instruction = join; | 504 *last_instruction = join; |
510 | 505 |
511 // If the call has uses, create a phi of the returns. | 506 // If the call has uses, create a phi of the returns. |
512 if (call_->HasUses()) { | 507 if (call_->HasUses()) { |
513 // Add a phi of the return values. | 508 // Add a phi of the return values. |
514 PhiInstr* phi = new(Z) PhiInstr(join, num_exits); | 509 PhiInstr* phi = new (Z) PhiInstr(join, num_exits); |
515 caller_graph_->AllocateSSAIndexes(phi); | 510 caller_graph_->AllocateSSAIndexes(phi); |
516 phi->mark_alive(); | 511 phi->mark_alive(); |
517 for (intptr_t i = 0; i < num_exits; ++i) { | 512 for (intptr_t i = 0; i < num_exits; ++i) { |
518 ReturnAt(i)->RemoveEnvironment(); | 513 ReturnAt(i)->RemoveEnvironment(); |
519 phi->SetInputAt(i, ValueAt(i)); | 514 phi->SetInputAt(i, ValueAt(i)); |
520 } | 515 } |
521 join->InsertPhi(phi); | 516 join->InsertPhi(phi); |
522 join->InheritDeoptTargetAfter(caller_graph_, call_, phi); | 517 join->InheritDeoptTargetAfter(caller_graph_, call_, phi); |
523 return phi; | 518 return phi; |
524 } else { | 519 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
543 BlockEntryInstr* callee_exit = NULL; | 538 BlockEntryInstr* callee_exit = NULL; |
544 Instruction* callee_last_instruction = NULL; | 539 Instruction* callee_last_instruction = NULL; |
545 | 540 |
546 if (exits_.length() == 0) { | 541 if (exits_.length() == 0) { |
547 // Handle the case when there are no normal return exits from the callee | 542 // Handle the case when there are no normal return exits from the callee |
548 // (i.e. the callee unconditionally throws) by inserting an artificial | 543 // (i.e. the callee unconditionally throws) by inserting an artificial |
549 // branch (true === true). | 544 // branch (true === true). |
550 // The true successor is the inlined body, the false successor | 545 // The true successor is the inlined body, the false successor |
551 // goes to the rest of the caller graph. It is removed as unreachable code | 546 // goes to the rest of the caller graph. It is removed as unreachable code |
552 // by the constant propagation. | 547 // by the constant propagation. |
553 TargetEntryInstr* false_block = | 548 TargetEntryInstr* false_block = new (Z) TargetEntryInstr( |
554 new(Z) TargetEntryInstr(caller_graph_->allocate_block_id(), | 549 caller_graph_->allocate_block_id(), call_block->try_index()); |
555 call_block->try_index()); | |
556 false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL); | 550 false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL); |
557 false_block->LinkTo(call_->next()); | 551 false_block->LinkTo(call_->next()); |
558 call_block->ReplaceAsPredecessorWith(false_block); | 552 call_block->ReplaceAsPredecessorWith(false_block); |
559 | 553 |
560 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); | 554 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); |
561 BranchInstr* branch = | 555 BranchInstr* branch = new (Z) BranchInstr(new (Z) StrictCompareInstr( |
562 new(Z) BranchInstr( | 556 TokenPosition::kNoSource, Token::kEQ_STRICT, new (Z) Value(true_const), |
563 new(Z) StrictCompareInstr(TokenPosition::kNoSource, | 557 new (Z) Value(true_const), |
564 Token::kEQ_STRICT, | 558 false)); // No number check. |
565 new(Z) Value(true_const), | |
566 new(Z) Value(true_const), | |
567 false)); // No number check. | |
568 branch->InheritDeoptTarget(zone(), call_); | 559 branch->InheritDeoptTarget(zone(), call_); |
569 *branch->true_successor_address() = callee_entry; | 560 *branch->true_successor_address() = callee_entry; |
570 *branch->false_successor_address() = false_block; | 561 *branch->false_successor_address() = false_block; |
571 | 562 |
572 call_->previous()->AppendInstruction(branch); | 563 call_->previous()->AppendInstruction(branch); |
573 call_block->set_last_instruction(branch); | 564 call_block->set_last_instruction(branch); |
574 | 565 |
575 // Replace uses of the return value with null to maintain valid | 566 // Replace uses of the return value with null to maintain valid |
576 // SSA form - even though the rest of the caller is unreachable. | 567 // SSA form - even though the rest of the caller is unreachable. |
577 call_->ReplaceUsesWith(caller_graph_->constant_null()); | 568 call_->ReplaceUsesWith(caller_graph_->constant_null()); |
578 | 569 |
579 // Update dominator tree. | 570 // Update dominator tree. |
580 call_block->AddDominatedBlock(callee_entry); | 571 call_block->AddDominatedBlock(callee_entry); |
581 call_block->AddDominatedBlock(false_block); | 572 call_block->AddDominatedBlock(false_block); |
582 | 573 |
583 } else { | 574 } else { |
584 Definition* callee_result = JoinReturns(&callee_exit, | 575 Definition* callee_result = JoinReturns( |
585 &callee_last_instruction, | 576 &callee_exit, &callee_last_instruction, call_block->try_index()); |
586 call_block->try_index()); | |
587 if (callee_result != NULL) { | 577 if (callee_result != NULL) { |
588 call_->ReplaceUsesWith(callee_result); | 578 call_->ReplaceUsesWith(callee_result); |
589 } | 579 } |
590 if (callee_last_instruction == callee_entry) { | 580 if (callee_last_instruction == callee_entry) { |
591 // There are no instructions in the inlined function (e.g., it might be | 581 // There are no instructions in the inlined function (e.g., it might be |
592 // a return of a parameter or a return of a constant defined in the | 582 // a return of a parameter or a return of a constant defined in the |
593 // initial definitions). | 583 // initial definitions). |
594 call_->previous()->LinkTo(call_->next()); | 584 call_->previous()->LinkTo(call_->next()); |
595 } else { | 585 } else { |
596 call_->previous()->LinkTo(callee_entry->next()); | 586 call_->previous()->LinkTo(callee_entry->next()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 ASSERT(is_open()); | 658 ASSERT(is_open()); |
669 owner()->DeallocateTemps(definition->InputCount()); | 659 owner()->DeallocateTemps(definition->InputCount()); |
670 owner()->add_args_pushed(-definition->ArgumentCount()); | 660 owner()->add_args_pushed(-definition->ArgumentCount()); |
671 definition->set_temp_index(owner()->AllocateTemp()); | 661 definition->set_temp_index(owner()->AllocateTemp()); |
672 if (is_empty()) { | 662 if (is_empty()) { |
673 entry_ = definition; | 663 entry_ = definition; |
674 } else { | 664 } else { |
675 exit()->LinkTo(definition); | 665 exit()->LinkTo(definition); |
676 } | 666 } |
677 exit_ = definition; | 667 exit_ = definition; |
678 return new(Z) Value(definition); | 668 return new (Z) Value(definition); |
679 } | 669 } |
680 | 670 |
681 | 671 |
682 void EffectGraphVisitor::Do(Definition* definition) { | 672 void EffectGraphVisitor::Do(Definition* definition) { |
683 ASSERT(is_open()); | 673 ASSERT(is_open()); |
684 owner()->DeallocateTemps(definition->InputCount()); | 674 owner()->DeallocateTemps(definition->InputCount()); |
685 owner()->add_args_pushed(-definition->ArgumentCount()); | 675 owner()->add_args_pushed(-definition->ArgumentCount()); |
686 if (is_empty()) { | 676 if (is_empty()) { |
687 entry_ = definition; | 677 entry_ = definition; |
688 } else { | 678 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
700 owner()->add_args_pushed(-instruction->ArgumentCount()); | 690 owner()->add_args_pushed(-instruction->ArgumentCount()); |
701 if (is_empty()) { | 691 if (is_empty()) { |
702 entry_ = exit_ = instruction; | 692 entry_ = exit_ = instruction; |
703 } else { | 693 } else { |
704 exit()->LinkTo(instruction); | 694 exit()->LinkTo(instruction); |
705 exit_ = instruction; | 695 exit_ = instruction; |
706 } | 696 } |
707 } | 697 } |
708 | 698 |
709 | 699 |
710 void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, | 700 void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) { |
711 Value* value) { | |
712 ASSERT(is_open()); | 701 ASSERT(is_open()); |
713 ReturnInstr* return_instr = new(Z) ReturnInstr(token_pos, value); | 702 ReturnInstr* return_instr = new (Z) ReturnInstr(token_pos, value); |
714 AddInstruction(return_instr); | 703 AddInstruction(return_instr); |
715 InlineExitCollector* exit_collector = owner()->exit_collector(); | 704 InlineExitCollector* exit_collector = owner()->exit_collector(); |
716 if (exit_collector != NULL) { | 705 if (exit_collector != NULL) { |
717 exit_collector->AddExit(return_instr); | 706 exit_collector->AddExit(return_instr); |
718 } | 707 } |
719 CloseFragment(); | 708 CloseFragment(); |
720 } | 709 } |
721 | 710 |
722 | 711 |
723 void EffectGraphVisitor::Goto(JoinEntryInstr* join) { | 712 void EffectGraphVisitor::Goto(JoinEntryInstr* join) { |
724 ASSERT(is_open()); | 713 ASSERT(is_open()); |
725 if (is_empty()) { | 714 if (is_empty()) { |
726 entry_ = new(Z) GotoInstr(join); | 715 entry_ = new (Z) GotoInstr(join); |
727 } else { | 716 } else { |
728 exit()->Goto(join); | 717 exit()->Goto(join); |
729 } | 718 } |
730 CloseFragment(); | 719 CloseFragment(); |
731 } | 720 } |
732 | 721 |
733 | 722 |
734 // Appends a graph fragment to a block entry instruction. Returns the entry | 723 // Appends a graph fragment to a block entry instruction. Returns the entry |
735 // instruction if the fragment was empty or else the exit of the fragment if | 724 // instruction if the fragment was empty or else the exit of the fragment if |
736 // it was non-empty (so NULL if the fragment is closed). | 725 // it was non-empty (so NULL if the fragment is closed). |
(...skipping 28 matching lines...) Expand all Loading... |
765 | 754 |
766 BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor(); | 755 BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor(); |
767 Instruction* false_exit = AppendFragment(false_entry, false_fragment); | 756 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
768 | 757 |
769 // 3. Add a join or select one (or neither) of the arms as exit. | 758 // 3. Add a join or select one (or neither) of the arms as exit. |
770 if (true_exit == NULL) { | 759 if (true_exit == NULL) { |
771 exit_ = false_exit; // May be NULL. | 760 exit_ = false_exit; // May be NULL. |
772 } else if (false_exit == NULL) { | 761 } else if (false_exit == NULL) { |
773 exit_ = true_exit; | 762 exit_ = true_exit; |
774 } else { | 763 } else { |
775 JoinEntryInstr* join = | 764 JoinEntryInstr* join = new (Z) |
776 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 765 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
777 true_exit->Goto(join); | 766 true_exit->Goto(join); |
778 false_exit->Goto(join); | 767 false_exit->Goto(join); |
779 exit_ = join; | 768 exit_ = join; |
780 } | 769 } |
781 } | 770 } |
782 | 771 |
783 | 772 |
784 void EffectGraphVisitor::TieLoop( | 773 void EffectGraphVisitor::TieLoop( |
785 TokenPosition token_pos, | 774 TokenPosition token_pos, |
786 const TestGraphVisitor& test_fragment, | 775 const TestGraphVisitor& test_fragment, |
787 const EffectGraphVisitor& body_fragment, | 776 const EffectGraphVisitor& body_fragment, |
788 const EffectGraphVisitor& test_preamble_fragment) { | 777 const EffectGraphVisitor& test_preamble_fragment) { |
789 // We have: a test graph fragment with zero, one, or two available exits; | 778 // We have: a test graph fragment with zero, one, or two available exits; |
790 // and an effect graph fragment with zero or one available exits. We want | 779 // and an effect graph fragment with zero or one available exits. We want |
791 // to append the 'while loop' consisting of the test graph fragment as | 780 // to append the 'while loop' consisting of the test graph fragment as |
792 // condition and the effect graph fragment as body. | 781 // condition and the effect graph fragment as body. |
793 ASSERT(is_open()); | 782 ASSERT(is_open()); |
794 | 783 |
795 // 1. Connect the body to the test if it is reachable, and if so record | 784 // 1. Connect the body to the test if it is reachable, and if so record |
796 // its exit (if any). | 785 // its exit (if any). |
797 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); | 786 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); |
798 Instruction* body_exit = AppendFragment(body_entry, body_fragment); | 787 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
799 | 788 |
800 // 2. Connect the test to this graph, including the body if reachable and | 789 // 2. Connect the test to this graph, including the body if reachable and |
801 // using a fresh join node if the body is reachable and has an open exit. | 790 // using a fresh join node if the body is reachable and has an open exit. |
802 if (body_exit == NULL) { | 791 if (body_exit == NULL) { |
803 Append(test_preamble_fragment); | 792 Append(test_preamble_fragment); |
804 Append(test_fragment); | 793 Append(test_fragment); |
805 } else { | 794 } else { |
806 JoinEntryInstr* join = | 795 JoinEntryInstr* join = new (Z) |
807 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 796 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
808 CheckStackOverflowInstr* check = | 797 CheckStackOverflowInstr* check = |
809 new(Z) CheckStackOverflowInstr(token_pos, owner()->loop_depth()); | 798 new (Z) CheckStackOverflowInstr(token_pos, owner()->loop_depth()); |
810 join->LinkTo(check); | 799 join->LinkTo(check); |
811 if (!test_preamble_fragment.is_empty()) { | 800 if (!test_preamble_fragment.is_empty()) { |
812 check->LinkTo(test_preamble_fragment.entry()); | 801 check->LinkTo(test_preamble_fragment.entry()); |
813 test_preamble_fragment.exit()->LinkTo(test_fragment.entry()); | 802 test_preamble_fragment.exit()->LinkTo(test_fragment.entry()); |
814 } else { | 803 } else { |
815 check->LinkTo(test_fragment.entry()); | 804 check->LinkTo(test_fragment.entry()); |
816 } | 805 } |
817 Goto(join); | 806 Goto(join); |
818 body_exit->Goto(join); | 807 body_exit->Goto(join); |
819 } | 808 } |
820 | 809 |
821 // 3. Set the exit to the graph to be the false successor of the test, a | 810 // 3. Set the exit to the graph to be the false successor of the test, a |
822 // fresh target node | 811 // fresh target node |
823 exit_ = test_fragment.CreateFalseSuccessor(); | 812 exit_ = test_fragment.CreateFalseSuccessor(); |
824 } | 813 } |
825 | 814 |
826 | 815 |
827 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { | 816 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { |
828 owner_->add_args_pushed(1); | 817 owner_->add_args_pushed(1); |
829 PushArgumentInstr* result = new(Z) PushArgumentInstr(value); | 818 PushArgumentInstr* result = new (Z) PushArgumentInstr(value); |
830 AddInstruction(result); | 819 AddInstruction(result); |
831 return result; | 820 return result; |
832 } | 821 } |
833 | 822 |
834 | 823 |
835 Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local, | 824 Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local, |
836 Value* value, | 825 Value* value, |
837 TokenPosition token_pos) { | 826 TokenPosition token_pos) { |
838 ASSERT(!local.is_captured()); | 827 ASSERT(!local.is_captured()); |
839 ASSERT(!token_pos.IsClassifying()); | 828 ASSERT(!token_pos.IsClassifying()); |
840 return new(Z) StoreLocalInstr(local, value, ST(token_pos)); | 829 return new (Z) StoreLocalInstr(local, value, ST(token_pos)); |
841 } | 830 } |
842 | 831 |
843 | 832 |
844 Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value, | 833 Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value, |
845 TokenPosition token_pos) { | 834 TokenPosition token_pos) { |
846 return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(), | 835 return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(), |
847 value, | 836 value, token_pos); |
848 token_pos); | |
849 } | 837 } |
850 | 838 |
851 | 839 |
852 Definition* EffectGraphVisitor::BuildLoadExprTemp(TokenPosition token_pos) { | 840 Definition* EffectGraphVisitor::BuildLoadExprTemp(TokenPosition token_pos) { |
853 ASSERT(!token_pos.IsClassifying()); | 841 ASSERT(!token_pos.IsClassifying()); |
854 return BuildLoadLocal(*owner()->parsed_function().expression_temp_var(), | 842 return BuildLoadLocal(*owner()->parsed_function().expression_temp_var(), |
855 token_pos); | 843 token_pos); |
856 } | 844 } |
857 | 845 |
858 | 846 |
859 Definition* EffectGraphVisitor::BuildStoreLocal(const LocalVariable& local, | 847 Definition* EffectGraphVisitor::BuildStoreLocal(const LocalVariable& local, |
860 Value* value, | 848 Value* value, |
861 TokenPosition token_pos) { | 849 TokenPosition token_pos) { |
862 if (local.is_captured()) { | 850 if (local.is_captured()) { |
863 LocalVariable* tmp_var = EnterTempLocalScope(value); | 851 LocalVariable* tmp_var = EnterTempLocalScope(value); |
864 intptr_t delta = | 852 intptr_t delta = owner()->context_level() - local.owner()->context_level(); |
865 owner()->context_level() - local.owner()->context_level(); | |
866 ASSERT(delta >= 0); | 853 ASSERT(delta >= 0); |
867 Value* context = Bind(BuildCurrentContext(token_pos)); | 854 Value* context = Bind(BuildCurrentContext(token_pos)); |
868 while (delta-- > 0) { | 855 while (delta-- > 0) { |
869 context = Bind(new(Z) LoadFieldInstr( | 856 context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(), |
870 context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()), | 857 Type::ZoneHandle(Z, Type::null()), |
871 token_pos)); | 858 token_pos)); |
872 } | 859 } |
873 Value* tmp_val = Bind(new(Z) LoadLocalInstr(*tmp_var, token_pos)); | 860 Value* tmp_val = Bind(new (Z) LoadLocalInstr(*tmp_var, token_pos)); |
874 StoreInstanceFieldInstr* store = | 861 StoreInstanceFieldInstr* store = new (Z) |
875 new(Z) StoreInstanceFieldInstr(Context::variable_offset(local.index()), | 862 StoreInstanceFieldInstr(Context::variable_offset(local.index()), |
876 context, | 863 context, tmp_val, kEmitStoreBarrier, token_pos); |
877 tmp_val, | |
878 kEmitStoreBarrier, | |
879 token_pos); | |
880 Do(store); | 864 Do(store); |
881 return ExitTempLocalScope(value); | 865 return ExitTempLocalScope(value); |
882 } else { | 866 } else { |
883 return new(Z) StoreLocalInstr(local, value, token_pos); | 867 return new (Z) StoreLocalInstr(local, value, token_pos); |
884 } | 868 } |
885 } | 869 } |
886 | 870 |
887 | 871 |
888 Definition* EffectGraphVisitor::BuildLoadLocal(const LocalVariable& local, | 872 Definition* EffectGraphVisitor::BuildLoadLocal(const LocalVariable& local, |
889 TokenPosition token_pos) { | 873 TokenPosition token_pos) { |
890 if (local.IsConst()) { | 874 if (local.IsConst()) { |
891 return new(Z) ConstantInstr(*local.ConstValue(), token_pos); | 875 return new (Z) ConstantInstr(*local.ConstValue(), token_pos); |
892 } else if (local.is_captured()) { | 876 } else if (local.is_captured()) { |
893 intptr_t delta = | 877 intptr_t delta = owner()->context_level() - local.owner()->context_level(); |
894 owner()->context_level() - local.owner()->context_level(); | |
895 ASSERT(delta >= 0); | 878 ASSERT(delta >= 0); |
896 Value* context = Bind(BuildCurrentContext(token_pos)); | 879 Value* context = Bind(BuildCurrentContext(token_pos)); |
897 while (delta-- > 0) { | 880 while (delta-- > 0) { |
898 context = Bind(new(Z) LoadFieldInstr( | 881 context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(), |
899 context, Context::parent_offset(), Type::ZoneHandle(Z, Type::null()), | 882 Type::ZoneHandle(Z, Type::null()), |
900 token_pos)); | 883 token_pos)); |
901 } | 884 } |
902 LoadFieldInstr* load = new(Z) LoadFieldInstr( | 885 LoadFieldInstr* load = |
903 context, | 886 new (Z) LoadFieldInstr(context, Context::variable_offset(local.index()), |
904 Context::variable_offset(local.index()), | 887 local.type(), token_pos); |
905 local.type(), | |
906 token_pos); | |
907 load->set_is_immutable(local.is_final()); | 888 load->set_is_immutable(local.is_final()); |
908 return load; | 889 return load; |
909 } else { | 890 } else { |
910 return new(Z) LoadLocalInstr(local, token_pos); | 891 return new (Z) LoadLocalInstr(local, token_pos); |
911 } | 892 } |
912 } | 893 } |
913 | 894 |
914 | 895 |
915 // Stores current context into the 'variable' | 896 // Stores current context into the 'variable' |
916 void EffectGraphVisitor::BuildSaveContext( | 897 void EffectGraphVisitor::BuildSaveContext(const LocalVariable& variable, |
917 const LocalVariable& variable, | 898 TokenPosition token_pos) { |
918 TokenPosition token_pos) { | |
919 ASSERT(token_pos.IsSynthetic() || token_pos.IsNoSource()); | 899 ASSERT(token_pos.IsSynthetic() || token_pos.IsNoSource()); |
920 Value* context = Bind(BuildCurrentContext(token_pos)); | 900 Value* context = Bind(BuildCurrentContext(token_pos)); |
921 Do(BuildStoreLocal(variable, context, token_pos)); | 901 Do(BuildStoreLocal(variable, context, token_pos)); |
922 } | 902 } |
923 | 903 |
924 | 904 |
925 // Loads context saved in 'context_variable' into the current context. | 905 // Loads context saved in 'context_variable' into the current context. |
926 void EffectGraphVisitor::BuildRestoreContext( | 906 void EffectGraphVisitor::BuildRestoreContext(const LocalVariable& variable, |
927 const LocalVariable& variable, | 907 TokenPosition token_pos) { |
928 TokenPosition token_pos) { | |
929 Value* load_saved_context = Bind(BuildLoadLocal(variable, token_pos)); | 908 Value* load_saved_context = Bind(BuildLoadLocal(variable, token_pos)); |
930 Do(BuildStoreContext(load_saved_context, token_pos)); | 909 Do(BuildStoreContext(load_saved_context, token_pos)); |
931 } | 910 } |
932 | 911 |
933 | 912 |
934 Definition* EffectGraphVisitor::BuildStoreContext( | 913 Definition* EffectGraphVisitor::BuildStoreContext(Value* value, |
935 Value* value, TokenPosition token_pos) { | 914 TokenPosition token_pos) { |
936 return new(Z) StoreLocalInstr( | 915 return new (Z) StoreLocalInstr( |
937 *owner()->parsed_function().current_context_var(), value, token_pos); | 916 *owner()->parsed_function().current_context_var(), value, token_pos); |
938 } | 917 } |
939 | 918 |
940 | 919 |
941 Definition* EffectGraphVisitor::BuildCurrentContext(TokenPosition token_pos) { | 920 Definition* EffectGraphVisitor::BuildCurrentContext(TokenPosition token_pos) { |
942 return new(Z) LoadLocalInstr( | 921 return new (Z) LoadLocalInstr( |
943 *owner()->parsed_function().current_context_var(), | 922 *owner()->parsed_function().current_context_var(), token_pos); |
944 token_pos); | |
945 } | 923 } |
946 | 924 |
947 | 925 |
948 void TestGraphVisitor::ConnectBranchesTo( | 926 void TestGraphVisitor::ConnectBranchesTo( |
949 const GrowableArray<TargetEntryInstr**>& branches, | 927 const GrowableArray<TargetEntryInstr**>& branches, |
950 JoinEntryInstr* join) const { | 928 JoinEntryInstr* join) const { |
951 ASSERT(!branches.is_empty()); | 929 ASSERT(!branches.is_empty()); |
952 for (intptr_t i = 0; i < branches.length(); i++) { | 930 for (intptr_t i = 0; i < branches.length(); i++) { |
953 TargetEntryInstr* target = | 931 TargetEntryInstr* target = new (Z) |
954 new(Z) TargetEntryInstr(owner()->AllocateBlockId(), | 932 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
955 owner()->try_index()); | |
956 *(branches[i]) = target; | 933 *(branches[i]) = target; |
957 target->Goto(join); | 934 target->Goto(join); |
958 } | 935 } |
959 } | 936 } |
960 | 937 |
961 | 938 |
962 void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const { | 939 void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const { |
963 ConnectBranchesTo(true_successor_addresses_, join); | 940 ConnectBranchesTo(true_successor_addresses_, join); |
964 } | 941 } |
965 | 942 |
966 | 943 |
967 void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const { | 944 void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const { |
968 ConnectBranchesTo(false_successor_addresses_, join); | 945 ConnectBranchesTo(false_successor_addresses_, join); |
969 } | 946 } |
970 | 947 |
971 | 948 |
972 BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor( | 949 BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor( |
973 const GrowableArray<TargetEntryInstr**>& branches) const { | 950 const GrowableArray<TargetEntryInstr**>& branches) const { |
974 ASSERT(!branches.is_empty()); | 951 ASSERT(!branches.is_empty()); |
975 | 952 |
976 if (branches.length() == 1) { | 953 if (branches.length() == 1) { |
977 TargetEntryInstr* target = | 954 TargetEntryInstr* target = new (Z) |
978 new(Z) TargetEntryInstr(owner()->AllocateBlockId(), | 955 TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
979 owner()->try_index()); | |
980 *(branches[0]) = target; | 956 *(branches[0]) = target; |
981 return target; | 957 return target; |
982 } | 958 } |
983 | 959 |
984 JoinEntryInstr* join = | 960 JoinEntryInstr* join = |
985 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 961 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
986 ConnectBranchesTo(branches, join); | 962 ConnectBranchesTo(branches, join); |
987 return join; | 963 return join; |
988 } | 964 } |
989 | 965 |
990 | 966 |
991 BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const { | 967 BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const { |
992 return CreateSuccessorFor(true_successor_addresses_); | 968 return CreateSuccessorFor(true_successor_addresses_); |
993 } | 969 } |
994 | 970 |
995 | 971 |
996 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { | 972 BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const { |
997 return CreateSuccessorFor(false_successor_addresses_); | 973 return CreateSuccessorFor(false_successor_addresses_); |
998 } | 974 } |
999 | 975 |
1000 | 976 |
1001 void TestGraphVisitor::ReturnValue(Value* value) { | 977 void TestGraphVisitor::ReturnValue(Value* value) { |
1002 Isolate* isolate = Isolate::Current(); | 978 Isolate* isolate = Isolate::Current(); |
1003 if (isolate->type_checks() || isolate->asserts()) { | 979 if (isolate->type_checks() || isolate->asserts()) { |
1004 value = Bind(new(Z) AssertBooleanInstr(condition_token_pos(), value)); | 980 value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value)); |
1005 } | 981 } |
1006 Value* constant_true = Bind(new(Z) ConstantInstr(Bool::True())); | 982 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); |
1007 StrictCompareInstr* comp = | 983 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
1008 new(Z) StrictCompareInstr(condition_token_pos(), | 984 condition_token_pos(), Token::kEQ_STRICT, value, constant_true, |
1009 Token::kEQ_STRICT, | 985 false); // No number check. |
1010 value, | 986 BranchInstr* branch = new (Z) BranchInstr(comp); |
1011 constant_true, | |
1012 false); // No number check. | |
1013 BranchInstr* branch = new(Z) BranchInstr(comp); | |
1014 AddInstruction(branch); | 987 AddInstruction(branch); |
1015 CloseFragment(); | 988 CloseFragment(); |
1016 | 989 |
1017 true_successor_addresses_.Add(branch->true_successor_address()); | 990 true_successor_addresses_.Add(branch->true_successor_address()); |
1018 false_successor_addresses_.Add(branch->false_successor_address()); | 991 false_successor_addresses_.Add(branch->false_successor_address()); |
1019 } | 992 } |
1020 | 993 |
1021 | 994 |
1022 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { | 995 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { |
1023 BranchInstr* branch; | 996 BranchInstr* branch; |
1024 if (Token::IsStrictEqualityOperator(comp->kind())) { | 997 if (Token::IsStrictEqualityOperator(comp->kind())) { |
1025 ASSERT(comp->IsStrictCompare()); | 998 ASSERT(comp->IsStrictCompare()); |
1026 branch = new(Z) BranchInstr(comp); | 999 branch = new (Z) BranchInstr(comp); |
1027 } else if (Token::IsEqualityOperator(comp->kind()) && | 1000 } else if (Token::IsEqualityOperator(comp->kind()) && |
1028 (comp->left()->BindsToConstantNull() || | 1001 (comp->left()->BindsToConstantNull() || |
1029 comp->right()->BindsToConstantNull())) { | 1002 comp->right()->BindsToConstantNull())) { |
1030 branch = new(Z) BranchInstr(new(Z) StrictCompareInstr( | 1003 branch = new (Z) BranchInstr(new (Z) StrictCompareInstr( |
1031 comp->token_pos(), | 1004 comp->token_pos(), |
1032 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 1005 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
1033 comp->left(), | 1006 comp->left(), comp->right(), |
1034 comp->right(), | |
1035 false)); // No number check. | 1007 false)); // No number check. |
1036 } else { | 1008 } else { |
1037 branch = new(Z) BranchInstr(comp); | 1009 branch = new (Z) BranchInstr(comp); |
1038 branch->set_is_checked(Isolate::Current()->type_checks()); | 1010 branch->set_is_checked(Isolate::Current()->type_checks()); |
1039 } | 1011 } |
1040 AddInstruction(branch); | 1012 AddInstruction(branch); |
1041 CloseFragment(); | 1013 CloseFragment(); |
1042 true_successor_addresses_.Add(branch->true_successor_address()); | 1014 true_successor_addresses_.Add(branch->true_successor_address()); |
1043 false_successor_addresses_.Add(branch->false_successor_address()); | 1015 false_successor_addresses_.Add(branch->false_successor_address()); |
1044 } | 1016 } |
1045 | 1017 |
1046 | 1018 |
1047 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 1019 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
1048 ASSERT(!Isolate::Current()->type_checks()); | 1020 ASSERT(!Isolate::Current()->type_checks()); |
1049 Value* constant_true = Bind(new(Z) ConstantInstr(Bool::True())); | 1021 Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True())); |
1050 StrictCompareInstr* comp = | 1022 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
1051 new(Z) StrictCompareInstr(condition_token_pos(), | 1023 condition_token_pos(), Token::kNE_STRICT, neg->value(), constant_true, |
1052 Token::kNE_STRICT, | 1024 false); // No number check. |
1053 neg->value(), | 1025 BranchInstr* branch = new (Z) BranchInstr(comp); |
1054 constant_true, | |
1055 false); // No number check. | |
1056 BranchInstr* branch = new(Z) BranchInstr(comp); | |
1057 AddInstruction(branch); | 1026 AddInstruction(branch); |
1058 CloseFragment(); | 1027 CloseFragment(); |
1059 true_successor_addresses_.Add(branch->true_successor_address()); | 1028 true_successor_addresses_.Add(branch->true_successor_address()); |
1060 false_successor_addresses_.Add(branch->false_successor_address()); | 1029 false_successor_addresses_.Add(branch->false_successor_address()); |
1061 } | 1030 } |
1062 | 1031 |
1063 | 1032 |
1064 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 1033 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
1065 ComparisonInstr* comp = definition->AsComparison(); | 1034 ComparisonInstr* comp = definition->AsComparison(); |
1066 if (comp != NULL) { | 1035 if (comp != NULL) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1128 node->value()->Visit(&for_value); | 1097 node->value()->Visit(&for_value); |
1129 Append(for_value); | 1098 Append(for_value); |
1130 Value* return_value = for_value.value(); | 1099 Value* return_value = for_value.value(); |
1131 | 1100 |
1132 // Call to stub that checks whether the debugger is in single | 1101 // Call to stub that checks whether the debugger is in single |
1133 // step mode. This call must happen before the contexts are | 1102 // step mode. This call must happen before the contexts are |
1134 // unchained so that captured variables can be inspected. | 1103 // unchained so that captured variables can be inspected. |
1135 // No debugger check is done in native functions or for return | 1104 // No debugger check is done in native functions or for return |
1136 // statements for which there is no associated source position. | 1105 // statements for which there is no associated source position. |
1137 const Function& function = owner()->function(); | 1106 const Function& function = owner()->function(); |
1138 if (FLAG_support_debugger && | 1107 if (FLAG_support_debugger && node->token_pos().IsDebugPause() && |
1139 node->token_pos().IsDebugPause() && | |
1140 !function.is_native()) { | 1108 !function.is_native()) { |
1141 AddInstruction(new(Z) DebugStepCheckInstr(node->token_pos(), | 1109 AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(), |
1142 RawPcDescriptors::kRuntimeCall)); | 1110 RawPcDescriptors::kRuntimeCall)); |
1143 } | 1111 } |
1144 | 1112 |
1145 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); | 1113 NestedContextAdjustment context_adjustment(owner(), owner()->context_level()); |
1146 | 1114 |
1147 if (node->inlined_finally_list_length() > 0) { | 1115 if (node->inlined_finally_list_length() > 0) { |
1148 LocalVariable* temp = owner()->parsed_function().finally_return_temp_var(); | 1116 LocalVariable* temp = owner()->parsed_function().finally_return_temp_var(); |
1149 ASSERT(temp != NULL); | 1117 ASSERT(temp != NULL); |
1150 Do(BuildStoreLocal(*temp, return_value, node->token_pos())); | 1118 Do(BuildStoreLocal(*temp, return_value, node->token_pos())); |
1151 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1119 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
1152 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); | 1120 InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)"); |
1153 EffectGraphVisitor for_effect(owner()); | 1121 EffectGraphVisitor for_effect(owner()); |
1154 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 1122 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
1155 Append(for_effect); | 1123 Append(for_effect); |
1156 if (!is_open()) { | 1124 if (!is_open()) { |
1157 return; | 1125 return; |
1158 } | 1126 } |
1159 } | 1127 } |
1160 return_value = Bind(BuildLoadLocal(*temp, node->token_pos())); | 1128 return_value = Bind(BuildLoadLocal(*temp, node->token_pos())); |
1161 } | 1129 } |
1162 | 1130 |
1163 if (Isolate::Current()->type_checks()) { | 1131 if (Isolate::Current()->type_checks()) { |
1164 const bool is_implicit_dynamic_getter = | 1132 const bool is_implicit_dynamic_getter = |
1165 (!function.is_static() && | 1133 (!function.is_static() && |
1166 ((function.kind() == RawFunction::kImplicitGetter) || | 1134 ((function.kind() == RawFunction::kImplicitGetter) || |
1167 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); | 1135 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); |
1168 // Implicit getters do not need a type check at return, unless they compute | 1136 // Implicit getters do not need a type check at return, unless they compute |
1169 // the initial value of a static field. | 1137 // the initial value of a static field. |
1170 // The body of a constructor cannot modify the type of the | 1138 // The body of a constructor cannot modify the type of the |
1171 // constructed instance, which is passed in as an implicit parameter. | 1139 // constructed instance, which is passed in as an implicit parameter. |
1172 // However, factories may create an instance of the wrong type. | 1140 // However, factories may create an instance of the wrong type. |
1173 if (!is_implicit_dynamic_getter && !function.IsGenerativeConstructor()) { | 1141 if (!is_implicit_dynamic_getter && !function.IsGenerativeConstructor()) { |
1174 const AbstractType& dst_type = | 1142 const AbstractType& dst_type = |
1175 AbstractType::ZoneHandle(Z, function.result_type()); | 1143 AbstractType::ZoneHandle(Z, function.result_type()); |
1176 return_value = BuildAssignableValue(node->value()->token_pos(), | 1144 return_value = |
1177 return_value, | 1145 BuildAssignableValue(node->value()->token_pos(), return_value, |
1178 dst_type, | 1146 dst_type, Symbols::FunctionResult()); |
1179 Symbols::FunctionResult()); | |
1180 } | 1147 } |
1181 } | 1148 } |
1182 | 1149 |
1183 // Async functions contain two types of return statements: | 1150 // Async functions contain two types of return statements: |
1184 // 1) Returns that should complete the completer once all finally blocks have | 1151 // 1) Returns that should complete the completer once all finally blocks have |
1185 // been inlined (call: :async_completer.complete(return_value)). These | 1152 // been inlined (call: :async_completer.complete(return_value)). These |
1186 // returns end up returning null in the end. | 1153 // returns end up returning null in the end. |
1187 // 2) "Continuation" returns that should not complete the completer but return | 1154 // 2) "Continuation" returns that should not complete the completer but return |
1188 // the value. | 1155 // the value. |
1189 // | 1156 // |
1190 // We distinguish those kinds of nodes via is_regular_return(). | 1157 // We distinguish those kinds of nodes via is_regular_return(). |
1191 // | 1158 // |
1192 if (function.IsAsyncClosure() && | 1159 if (function.IsAsyncClosure() && |
1193 (node->return_type() == ReturnNode::kRegular)) { | 1160 (node->return_type() == ReturnNode::kRegular)) { |
1194 // Temporary store the computed return value. | 1161 // Temporary store the computed return value. |
1195 Do(BuildStoreExprTemp(return_value, node->token_pos())); | 1162 Do(BuildStoreExprTemp(return_value, node->token_pos())); |
1196 | 1163 |
1197 LocalVariable* rcv_var = | 1164 LocalVariable* rcv_var = |
1198 node->scope()->LookupVariable(Symbols::AsyncCompleter(), false); | 1165 node->scope()->LookupVariable(Symbols::AsyncCompleter(), false); |
1199 ASSERT(rcv_var != NULL && rcv_var->is_captured()); | 1166 ASSERT(rcv_var != NULL && rcv_var->is_captured()); |
1200 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1167 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1201 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1168 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1202 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var, node->token_pos())); | 1169 Value* rcv_value = Bind(BuildLoadLocal(*rcv_var, node->token_pos())); |
1203 arguments->Add(PushArgument(rcv_value)); | 1170 arguments->Add(PushArgument(rcv_value)); |
1204 Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos())); | 1171 Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos())); |
1205 arguments->Add(PushArgument(returned_value)); | 1172 arguments->Add(PushArgument(returned_value)); |
1206 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 1173 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1207 node->token_pos(), | 1174 node->token_pos(), Symbols::CompleterComplete(), Token::kILLEGAL, |
1208 Symbols::CompleterComplete(), | 1175 arguments, Object::null_array(), 1, owner()->ic_data_array()); |
1209 Token::kILLEGAL, | |
1210 arguments, | |
1211 Object::null_array(), | |
1212 1, | |
1213 owner()->ic_data_array()); | |
1214 Do(call); | 1176 Do(call); |
1215 | 1177 |
1216 // Rebind the return value for the actual return call to be null. | 1178 // Rebind the return value for the actual return call to be null. |
1217 return_value = BuildNullValue(node->token_pos()); | 1179 return_value = BuildNullValue(node->token_pos()); |
1218 } | 1180 } |
1219 | 1181 |
1220 intptr_t current_context_level = owner()->context_level(); | 1182 intptr_t current_context_level = owner()->context_level(); |
1221 ASSERT(current_context_level >= 0); | 1183 ASSERT(current_context_level >= 0); |
1222 if (HasContextScope()) { | 1184 if (HasContextScope()) { |
1223 UnchainContexts(current_context_level); | 1185 UnchainContexts(current_context_level); |
1224 } | 1186 } |
1225 | 1187 |
1226 AddReturnExit(node->token_pos(), return_value); | 1188 AddReturnExit(node->token_pos(), return_value); |
1227 | 1189 |
1228 if ((function.IsAsyncClosure() || | 1190 if ((function.IsAsyncClosure() || function.IsSyncGenClosure() || |
1229 function.IsSyncGenClosure() || | 1191 function.IsAsyncGenClosure()) && |
1230 function.IsAsyncGenClosure()) && | |
1231 (node->return_type() == ReturnNode::kContinuationTarget)) { | 1192 (node->return_type() == ReturnNode::kContinuationTarget)) { |
1232 JoinEntryInstr* const join = new(Z) JoinEntryInstr( | 1193 JoinEntryInstr* const join = new (Z) |
1233 owner()->AllocateBlockId(), owner()->try_index()); | 1194 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
1234 owner()->await_joins()->Add(join); | 1195 owner()->await_joins()->Add(join); |
1235 exit_ = join; | 1196 exit_ = join; |
1236 } | 1197 } |
1237 } | 1198 } |
1238 | 1199 |
1239 | 1200 |
1240 // <Expression> ::= Literal { literal: Instance } | 1201 // <Expression> ::= Literal { literal: Instance } |
1241 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 1202 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
1242 ReturnDefinition(new(Z) ConstantInstr(node->literal(), node->token_pos())); | 1203 ReturnDefinition(new (Z) ConstantInstr(node->literal(), node->token_pos())); |
1243 } | 1204 } |
1244 | 1205 |
1245 | 1206 |
1246 // Type nodes are used when a type is referenced as a literal. Type nodes | 1207 // Type nodes are used when a type is referenced as a literal. Type nodes |
1247 // can also be used for the right-hand side of instanceof comparisons, | 1208 // can also be used for the right-hand side of instanceof comparisons, |
1248 // but they are handled specially in that context, not here. | 1209 // but they are handled specially in that context, not here. |
1249 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { | 1210 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { |
1250 return; | 1211 return; |
1251 } | 1212 } |
1252 | 1213 |
1253 | 1214 |
1254 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { | 1215 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { |
1255 const AbstractType& type = node->type(); | 1216 const AbstractType& type = node->type(); |
1256 // Type may be malbounded, but not malformed. | 1217 // Type may be malbounded, but not malformed. |
1257 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 1218 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
1258 if (type.IsInstantiated()) { | 1219 if (type.IsInstantiated()) { |
1259 ReturnDefinition(new(Z) ConstantInstr(type)); | 1220 ReturnDefinition(new (Z) ConstantInstr(type)); |
1260 } else { | 1221 } else { |
1261 const Class& instantiator_class = Class::ZoneHandle( | 1222 const Class& instantiator_class = |
1262 Z, owner()->function().Owner()); | 1223 Class::ZoneHandle(Z, owner()->function().Owner()); |
1263 Value* instantiator_value = BuildInstantiatorTypeArguments( | 1224 Value* instantiator_value = BuildInstantiatorTypeArguments( |
1264 node->token_pos(), instantiator_class, NULL); | 1225 node->token_pos(), instantiator_class, NULL); |
1265 ReturnDefinition(new(Z) InstantiateTypeInstr( | 1226 ReturnDefinition(new (Z) InstantiateTypeInstr( |
1266 node->token_pos(), type, instantiator_class, instantiator_value)); | 1227 node->token_pos(), type, instantiator_class, instantiator_value)); |
1267 } | 1228 } |
1268 } | 1229 } |
1269 | 1230 |
1270 | 1231 |
1271 // Returns true if the type check can be skipped, for example, if the | 1232 // Returns true if the type check can be skipped, for example, if the |
1272 // destination type is dynamic or if the compile type of the value is a subtype | 1233 // destination type is dynamic or if the compile type of the value is a subtype |
1273 // of the destination type. | 1234 // of the destination type. |
1274 bool EffectGraphVisitor::CanSkipTypeCheck(TokenPosition token_pos, | 1235 bool EffectGraphVisitor::CanSkipTypeCheck(TokenPosition token_pos, |
1275 Value* value, | 1236 Value* value, |
(...skipping 20 matching lines...) Expand all Loading... |
1296 | 1257 |
1297 // If nothing is known about the value, as is the case for passed-in | 1258 // If nothing is known about the value, as is the case for passed-in |
1298 // parameters, and since dst_type is not one of the tested cases above, then | 1259 // parameters, and since dst_type is not one of the tested cases above, then |
1299 // the type test cannot be eliminated. | 1260 // the type test cannot be eliminated. |
1300 if (value == NULL) { | 1261 if (value == NULL) { |
1301 return false; | 1262 return false; |
1302 } | 1263 } |
1303 | 1264 |
1304 const bool eliminated = value->Type()->IsAssignableTo(dst_type); | 1265 const bool eliminated = value->Type()->IsAssignableTo(dst_type); |
1305 if (FLAG_trace_type_check_elimination) { | 1266 if (FLAG_trace_type_check_elimination) { |
1306 FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(), | 1267 FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(), token_pos, |
1307 token_pos, | 1268 value, dst_type, dst_name, eliminated); |
1308 value, | |
1309 dst_type, | |
1310 dst_name, | |
1311 eliminated); | |
1312 } | 1269 } |
1313 return eliminated; | 1270 return eliminated; |
1314 } | 1271 } |
1315 | 1272 |
1316 | 1273 |
1317 // <Expression> :: Assignable { expr: <Expression> | 1274 // <Expression> :: Assignable { expr: <Expression> |
1318 // type: AbstractType | 1275 // type: AbstractType |
1319 // dst_name: String } | 1276 // dst_name: String } |
1320 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { | 1277 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
1321 ValueGraphVisitor for_value(owner()); | 1278 ValueGraphVisitor for_value(owner()); |
1322 node->expr()->Visit(&for_value); | 1279 node->expr()->Visit(&for_value); |
1323 Append(for_value); | 1280 Append(for_value); |
1324 if (CanSkipTypeCheck(node->expr()->token_pos(), | 1281 if (CanSkipTypeCheck(node->expr()->token_pos(), for_value.value(), |
1325 for_value.value(), | 1282 node->type(), node->dst_name())) { |
1326 node->type(), | |
1327 node->dst_name())) { | |
1328 ReturnValue(for_value.value()); | 1283 ReturnValue(for_value.value()); |
1329 } else { | 1284 } else { |
1330 ReturnDefinition(BuildAssertAssignable(node->expr()->token_pos(), | 1285 ReturnDefinition(BuildAssertAssignable(node->expr()->token_pos(), |
1331 for_value.value(), | 1286 for_value.value(), node->type(), |
1332 node->type(), | |
1333 node->dst_name())); | 1287 node->dst_name())); |
1334 } | 1288 } |
1335 } | 1289 } |
1336 | 1290 |
1337 | 1291 |
1338 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) { | 1292 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) { |
1339 ValueGraphVisitor for_value(owner()); | 1293 ValueGraphVisitor for_value(owner()); |
1340 node->expr()->Visit(&for_value); | 1294 node->expr()->Visit(&for_value); |
1341 Append(for_value); | 1295 Append(for_value); |
1342 ReturnValue(BuildAssignableValue(node->expr()->token_pos(), | 1296 ReturnValue(BuildAssignableValue(node->expr()->token_pos(), for_value.value(), |
1343 for_value.value(), | 1297 node->type(), node->dst_name())); |
1344 node->type(), | |
1345 node->dst_name())); | |
1346 } | 1298 } |
1347 | 1299 |
1348 | 1300 |
1349 // <Expression> :: BinaryOp { kind: Token::Kind | 1301 // <Expression> :: BinaryOp { kind: Token::Kind |
1350 // left: <Expression> | 1302 // left: <Expression> |
1351 // right: <Expression> } | 1303 // right: <Expression> } |
1352 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 1304 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
1353 // Operators "&&" and "||" cannot be overloaded therefore do not call | 1305 // Operators "&&" and "||" cannot be overloaded therefore do not call |
1354 // operator. | 1306 // operator. |
1355 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1307 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
1356 // See ValueGraphVisitor::VisitBinaryOpNode. | 1308 // See ValueGraphVisitor::VisitBinaryOpNode. |
1357 TestGraphVisitor for_left(owner(), node->left()->token_pos()); | 1309 TestGraphVisitor for_left(owner(), node->left()->token_pos()); |
1358 node->left()->Visit(&for_left); | 1310 node->left()->Visit(&for_left); |
1359 EffectGraphVisitor empty(owner()); | 1311 EffectGraphVisitor empty(owner()); |
1360 Isolate* isolate = Isolate::Current(); | 1312 Isolate* isolate = Isolate::Current(); |
1361 if (isolate->type_checks() || isolate->asserts()) { | 1313 if (isolate->type_checks() || isolate->asserts()) { |
1362 ValueGraphVisitor for_right(owner()); | 1314 ValueGraphVisitor for_right(owner()); |
1363 node->right()->Visit(&for_right); | 1315 node->right()->Visit(&for_right); |
1364 Value* right_value = for_right.value(); | 1316 Value* right_value = for_right.value(); |
1365 for_right.Do(new(Z) AssertBooleanInstr(node->right()->token_pos(), | 1317 for_right.Do( |
1366 right_value)); | 1318 new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value)); |
1367 if (node->kind() == Token::kAND) { | 1319 if (node->kind() == Token::kAND) { |
1368 Join(for_left, for_right, empty); | 1320 Join(for_left, for_right, empty); |
1369 } else { | 1321 } else { |
1370 Join(for_left, empty, for_right); | 1322 Join(for_left, empty, for_right); |
1371 } | 1323 } |
1372 } else { | 1324 } else { |
1373 EffectGraphVisitor for_right(owner()); | 1325 EffectGraphVisitor for_right(owner()); |
1374 node->right()->Visit(&for_right); | 1326 node->right()->Visit(&for_right); |
1375 if (node->kind() == Token::kAND) { | 1327 if (node->kind() == Token::kAND) { |
1376 Join(for_left, for_right, empty); | 1328 Join(for_left, for_right, empty); |
1377 } else { | 1329 } else { |
1378 Join(for_left, empty, for_right); | 1330 Join(for_left, empty, for_right); |
1379 } | 1331 } |
1380 } | 1332 } |
1381 return; | 1333 return; |
1382 } | 1334 } |
1383 ASSERT(node->kind() != Token::kIFNULL); | 1335 ASSERT(node->kind() != Token::kIFNULL); |
1384 ValueGraphVisitor for_left_value(owner()); | 1336 ValueGraphVisitor for_left_value(owner()); |
1385 node->left()->Visit(&for_left_value); | 1337 node->left()->Visit(&for_left_value); |
1386 Append(for_left_value); | 1338 Append(for_left_value); |
1387 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1339 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1388 | 1340 |
1389 ValueGraphVisitor for_right_value(owner()); | 1341 ValueGraphVisitor for_right_value(owner()); |
1390 node->right()->Visit(&for_right_value); | 1342 node->right()->Visit(&for_right_value); |
1391 Append(for_right_value); | 1343 Append(for_right_value); |
1392 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1344 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
1393 | 1345 |
1394 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1346 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1395 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1347 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1396 arguments->Add(push_left); | 1348 arguments->Add(push_left); |
1397 arguments->Add(push_right); | 1349 arguments->Add(push_right); |
1398 const String& name = Symbols::Token(node->kind()); | 1350 const String& name = Symbols::Token(node->kind()); |
1399 const intptr_t kNumArgsChecked = 2; | 1351 const intptr_t kNumArgsChecked = 2; |
1400 InstanceCallInstr* call = new(Z) InstanceCallInstr(node->token_pos(), | 1352 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1401 name, | 1353 node->token_pos(), name, node->kind(), arguments, Object::null_array(), |
1402 node->kind(), | 1354 kNumArgsChecked, owner()->ic_data_array()); |
1403 arguments, | |
1404 Object::null_array(), | |
1405 kNumArgsChecked, | |
1406 owner()->ic_data_array()); | |
1407 ReturnDefinition(call); | 1355 ReturnDefinition(call); |
1408 } | 1356 } |
1409 | 1357 |
1410 | 1358 |
1411 // Special handling for AND/OR. | 1359 // Special handling for AND/OR. |
1412 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 1360 void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
1413 // Operators "&&" and "||" cannot be overloaded therefore do not call | 1361 // Operators "&&" and "||" cannot be overloaded therefore do not call |
1414 // operator. | 1362 // operator. |
1415 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1363 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
1416 // Implement short-circuit logic: do not evaluate right if evaluation | 1364 // Implement short-circuit logic: do not evaluate right if evaluation |
1417 // of left is sufficient. | 1365 // of left is sufficient. |
1418 // AND: left ? right === true : false; | 1366 // AND: left ? right === true : false; |
1419 // OR: left ? true : right === true; | 1367 // OR: left ? true : right === true; |
1420 | 1368 |
1421 TestGraphVisitor for_test(owner(), node->left()->token_pos()); | 1369 TestGraphVisitor for_test(owner(), node->left()->token_pos()); |
1422 node->left()->Visit(&for_test); | 1370 node->left()->Visit(&for_test); |
1423 | 1371 |
1424 ValueGraphVisitor for_right(owner()); | 1372 ValueGraphVisitor for_right(owner()); |
1425 node->right()->Visit(&for_right); | 1373 node->right()->Visit(&for_right); |
1426 Value* right_value = for_right.value(); | 1374 Value* right_value = for_right.value(); |
1427 Isolate* isolate = Isolate::Current(); | 1375 Isolate* isolate = Isolate::Current(); |
1428 if (isolate->type_checks() || isolate->asserts()) { | 1376 if (isolate->type_checks() || isolate->asserts()) { |
1429 right_value = | 1377 right_value = for_right.Bind( |
1430 for_right.Bind(new(Z) AssertBooleanInstr(node->right()->token_pos(), | 1378 new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value)); |
1431 right_value)); | |
1432 } | 1379 } |
1433 Value* constant_true = for_right.Bind(new(Z) ConstantInstr(Bool::True())); | 1380 Value* constant_true = for_right.Bind(new (Z) ConstantInstr(Bool::True())); |
1434 Value* compare = | 1381 Value* compare = for_right.Bind(new (Z) StrictCompareInstr( |
1435 for_right.Bind(new(Z) StrictCompareInstr(node->token_pos(), | 1382 node->token_pos(), Token::kEQ_STRICT, right_value, constant_true, |
1436 Token::kEQ_STRICT, | 1383 false)); // No number check. |
1437 right_value, | |
1438 constant_true, | |
1439 false)); // No number check. | |
1440 for_right.Do(BuildStoreExprTemp(compare, node->token_pos())); | 1384 for_right.Do(BuildStoreExprTemp(compare, node->token_pos())); |
1441 | 1385 |
1442 if (node->kind() == Token::kAND) { | 1386 if (node->kind() == Token::kAND) { |
1443 ValueGraphVisitor for_false(owner()); | 1387 ValueGraphVisitor for_false(owner()); |
1444 Value* constant_false = | 1388 Value* constant_false = |
1445 for_false.Bind(new(Z) ConstantInstr(Bool::False())); | 1389 for_false.Bind(new (Z) ConstantInstr(Bool::False())); |
1446 for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos())); | 1390 for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos())); |
1447 Join(for_test, for_right, for_false); | 1391 Join(for_test, for_right, for_false); |
1448 } else { | 1392 } else { |
1449 ASSERT(node->kind() == Token::kOR); | 1393 ASSERT(node->kind() == Token::kOR); |
1450 ValueGraphVisitor for_true(owner()); | 1394 ValueGraphVisitor for_true(owner()); |
1451 Value* constant_true = for_true.Bind(new(Z) ConstantInstr(Bool::True())); | 1395 Value* constant_true = for_true.Bind(new (Z) ConstantInstr(Bool::True())); |
1452 for_true.Do(BuildStoreExprTemp(constant_true, node->token_pos())); | 1396 for_true.Do(BuildStoreExprTemp(constant_true, node->token_pos())); |
1453 Join(for_test, for_true, for_right); | 1397 Join(for_test, for_true, for_right); |
1454 } | 1398 } |
1455 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); | 1399 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); |
1456 return; | 1400 return; |
1457 } | 1401 } |
1458 | 1402 |
1459 EffectGraphVisitor::VisitBinaryOpNode(node); | 1403 EffectGraphVisitor::VisitBinaryOpNode(node); |
1460 } | 1404 } |
1461 | 1405 |
1462 | 1406 |
1463 void EffectGraphVisitor::BuildTypecheckPushArguments( | 1407 void EffectGraphVisitor::BuildTypecheckPushArguments( |
1464 TokenPosition token_pos, | 1408 TokenPosition token_pos, |
1465 PushArgumentInstr** push_instantiator_type_arguments_result) { | 1409 PushArgumentInstr** push_instantiator_type_arguments_result) { |
1466 const Class& instantiator_class = Class::Handle( | 1410 const Class& instantiator_class = |
1467 Z, owner()->function().Owner()); | 1411 Class::Handle(Z, owner()->function().Owner()); |
1468 // Since called only when type tested against is not instantiated. | 1412 // Since called only when type tested against is not instantiated. |
1469 ASSERT(instantiator_class.IsGeneric()); | 1413 ASSERT(instantiator_class.IsGeneric()); |
1470 Value* instantiator_type_arguments = NULL; | 1414 Value* instantiator_type_arguments = NULL; |
1471 Value* instantiator = BuildInstantiator(token_pos); | 1415 Value* instantiator = BuildInstantiator(token_pos); |
1472 if (instantiator == NULL) { | 1416 if (instantiator == NULL) { |
1473 // No instantiator when inside factory. | 1417 // No instantiator when inside factory. |
1474 instantiator_type_arguments = | 1418 instantiator_type_arguments = |
1475 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1419 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
1476 } else { | 1420 } else { |
1477 instantiator_type_arguments = BuildInstantiatorTypeArguments( | 1421 instantiator_type_arguments = BuildInstantiatorTypeArguments( |
1478 token_pos, instantiator_class, instantiator); | 1422 token_pos, instantiator_class, instantiator); |
1479 } | 1423 } |
1480 *push_instantiator_type_arguments_result = | 1424 *push_instantiator_type_arguments_result = |
1481 PushArgument(instantiator_type_arguments); | 1425 PushArgument(instantiator_type_arguments); |
1482 } | 1426 } |
1483 | 1427 |
1484 | 1428 |
1485 | |
1486 void EffectGraphVisitor::BuildTypecheckArguments( | 1429 void EffectGraphVisitor::BuildTypecheckArguments( |
1487 TokenPosition token_pos, | 1430 TokenPosition token_pos, |
1488 Value** instantiator_type_arguments_result) { | 1431 Value** instantiator_type_arguments_result) { |
1489 Value* instantiator = NULL; | 1432 Value* instantiator = NULL; |
1490 Value* instantiator_type_arguments = NULL; | 1433 Value* instantiator_type_arguments = NULL; |
1491 const Class& instantiator_class = Class::Handle( | 1434 const Class& instantiator_class = |
1492 Z, owner()->function().Owner()); | 1435 Class::Handle(Z, owner()->function().Owner()); |
1493 // Since called only when type tested against is not instantiated. | 1436 // Since called only when type tested against is not instantiated. |
1494 ASSERT(instantiator_class.IsGeneric()); | 1437 ASSERT(instantiator_class.IsGeneric()); |
1495 instantiator = BuildInstantiator(token_pos); | 1438 instantiator = BuildInstantiator(token_pos); |
1496 if (instantiator == NULL) { | 1439 if (instantiator == NULL) { |
1497 // No instantiator when inside factory. | 1440 // No instantiator when inside factory. |
1498 instantiator_type_arguments = | 1441 instantiator_type_arguments = |
1499 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1442 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
1500 } else { | 1443 } else { |
1501 instantiator_type_arguments = BuildInstantiatorTypeArguments( | 1444 instantiator_type_arguments = BuildInstantiatorTypeArguments( |
1502 token_pos, instantiator_class, instantiator); | 1445 token_pos, instantiator_class, instantiator); |
1503 } | 1446 } |
1504 *instantiator_type_arguments_result = instantiator_type_arguments; | 1447 *instantiator_type_arguments_result = instantiator_type_arguments; |
1505 } | 1448 } |
1506 | 1449 |
1507 | 1450 |
1508 Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) { | 1451 Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) { |
1509 return Bind(new(Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()), | 1452 return Bind( |
1510 token_pos)); | 1453 new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()), token_pos)); |
1511 } | 1454 } |
1512 | 1455 |
1513 | 1456 |
1514 // Used for testing incoming arguments. | 1457 // Used for testing incoming arguments. |
1515 AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable( | 1458 AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable( |
1516 TokenPosition token_pos, | 1459 TokenPosition token_pos, |
1517 Value* value, | 1460 Value* value, |
1518 const AbstractType& dst_type, | 1461 const AbstractType& dst_type, |
1519 const String& dst_name) { | 1462 const String& dst_name) { |
1520 // Build the type check computation. | 1463 // Build the type check computation. |
1521 Value* instantiator_type_arguments = NULL; | 1464 Value* instantiator_type_arguments = NULL; |
1522 if (dst_type.IsInstantiated()) { | 1465 if (dst_type.IsInstantiated()) { |
1523 instantiator_type_arguments = BuildNullValue(token_pos); | 1466 instantiator_type_arguments = BuildNullValue(token_pos); |
1524 } else { | 1467 } else { |
1525 BuildTypecheckArguments(token_pos, &instantiator_type_arguments); | 1468 BuildTypecheckArguments(token_pos, &instantiator_type_arguments); |
1526 } | 1469 } |
1527 | 1470 |
1528 const intptr_t deopt_id = Thread::Current()->GetNextDeoptId(); | 1471 const intptr_t deopt_id = Thread::Current()->GetNextDeoptId(); |
1529 return new(Z) AssertAssignableInstr(token_pos, | 1472 return new (Z) |
1530 value, | 1473 AssertAssignableInstr(token_pos, value, instantiator_type_arguments, |
1531 instantiator_type_arguments, | 1474 dst_type, dst_name, deopt_id); |
1532 dst_type, | |
1533 dst_name, | |
1534 deopt_id); | |
1535 } | 1475 } |
1536 | 1476 |
1537 | 1477 |
1538 // Used for type casts and to test assignments. | 1478 // Used for type casts and to test assignments. |
1539 Value* EffectGraphVisitor::BuildAssignableValue(TokenPosition token_pos, | 1479 Value* EffectGraphVisitor::BuildAssignableValue(TokenPosition token_pos, |
1540 Value* value, | 1480 Value* value, |
1541 const AbstractType& dst_type, | 1481 const AbstractType& dst_type, |
1542 const String& dst_name) { | 1482 const String& dst_name) { |
1543 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { | 1483 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) { |
1544 return value; | 1484 return value; |
(...skipping 25 matching lines...) Expand all Loading... |
1570 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); | 1510 ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); |
1571 const bool negate_result = (node->kind() == Token::kISNOT); | 1511 const bool negate_result = (node->kind() == Token::kISNOT); |
1572 // All objects are instances of type T if Object type is a subtype of type T. | 1512 // All objects are instances of type T if Object type is a subtype of type T. |
1573 const Type& object_type = Type::Handle(Z, Type::ObjectType()); | 1513 const Type& object_type = Type::Handle(Z, Type::ObjectType()); |
1574 if (type.IsInstantiated() && | 1514 if (type.IsInstantiated() && |
1575 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { | 1515 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { |
1576 // Must evaluate left side. | 1516 // Must evaluate left side. |
1577 EffectGraphVisitor for_left_value(owner()); | 1517 EffectGraphVisitor for_left_value(owner()); |
1578 node->left()->Visit(&for_left_value); | 1518 node->left()->Visit(&for_left_value); |
1579 Append(for_left_value); | 1519 Append(for_left_value); |
1580 ReturnDefinition(new(Z) ConstantInstr(Bool::Get(!negate_result))); | 1520 ReturnDefinition(new (Z) ConstantInstr(Bool::Get(!negate_result))); |
1581 return; | 1521 return; |
1582 } | 1522 } |
1583 ValueGraphVisitor for_left_value(owner()); | 1523 ValueGraphVisitor for_left_value(owner()); |
1584 node->left()->Visit(&for_left_value); | 1524 node->left()->Visit(&for_left_value); |
1585 Append(for_left_value); | 1525 Append(for_left_value); |
1586 | 1526 |
1587 if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() || | 1527 if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType() || |
1588 type.IsSmiType() || type.IsStringType()) { | 1528 type.IsSmiType() || type.IsStringType()) { |
1589 String& method_name = String::ZoneHandle(Z); | 1529 String& method_name = String::ZoneHandle(Z); |
1590 if (type.IsNumberType()) { | 1530 if (type.IsNumberType()) { |
1591 method_name = Symbols::_instanceOfNum().raw(); | 1531 method_name = Symbols::_instanceOfNum().raw(); |
1592 } else if (type.IsIntType()) { | 1532 } else if (type.IsIntType()) { |
1593 method_name = Symbols::_instanceOfInt().raw(); | 1533 method_name = Symbols::_instanceOfInt().raw(); |
1594 } else if (type.IsDoubleType()) { | 1534 } else if (type.IsDoubleType()) { |
1595 method_name = Symbols::_instanceOfDouble().raw(); | 1535 method_name = Symbols::_instanceOfDouble().raw(); |
1596 } else if (type.IsSmiType()) { | 1536 } else if (type.IsSmiType()) { |
1597 method_name = Symbols::_instanceOfSmi().raw(); | 1537 method_name = Symbols::_instanceOfSmi().raw(); |
1598 } else if (type.IsStringType()) { | 1538 } else if (type.IsStringType()) { |
1599 method_name = Symbols::_instanceOfString().raw(); | 1539 method_name = Symbols::_instanceOfString().raw(); |
1600 } | 1540 } |
1601 ASSERT(!method_name.IsNull()); | 1541 ASSERT(!method_name.IsNull()); |
1602 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1542 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1603 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1543 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1604 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1544 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1605 arguments->Add(push_left); | 1545 arguments->Add(push_left); |
1606 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); | 1546 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); |
1607 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); | 1547 Value* negate_arg = Bind(new (Z) ConstantInstr(negate)); |
1608 arguments->Add(PushArgument(negate_arg)); | 1548 arguments->Add(PushArgument(negate_arg)); |
1609 const intptr_t kNumArgsChecked = 1; | 1549 const intptr_t kNumArgsChecked = 1; |
1610 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 1550 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1611 node->token_pos(), | 1551 node->token_pos(), Library::PrivateCoreLibName(method_name), |
1612 Library::PrivateCoreLibName(method_name), | 1552 node->kind(), arguments, |
1613 node->kind(), | |
1614 arguments, | |
1615 Object::null_array(), // No argument names. | 1553 Object::null_array(), // No argument names. |
1616 kNumArgsChecked, | 1554 kNumArgsChecked, owner()->ic_data_array()); |
1617 owner()->ic_data_array()); | |
1618 ReturnDefinition(call); | 1555 ReturnDefinition(call); |
1619 return; | 1556 return; |
1620 } | 1557 } |
1621 | 1558 |
1622 // We now know type is a real class (!num, !int, !smi, !string) | 1559 // We now know type is a real class (!num, !int, !smi, !string) |
1623 // and the type check could NOT be removed at compile time. | 1560 // and the type check could NOT be removed at compile time. |
1624 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1561 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1625 if (simpleInstanceOfType(type)) { | 1562 if (simpleInstanceOfType(type)) { |
1626 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1563 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
1627 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1564 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1628 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1565 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1629 arguments->Add(push_left); | 1566 arguments->Add(push_left); |
1630 Value* type_const = Bind(new(Z) ConstantInstr(type)); | 1567 Value* type_const = Bind(new (Z) ConstantInstr(type)); |
1631 arguments->Add(PushArgument(type_const)); | 1568 arguments->Add(PushArgument(type_const)); |
1632 const intptr_t kNumArgsChecked = 2; | 1569 const intptr_t kNumArgsChecked = 2; |
1633 Definition* result = new(Z) InstanceCallInstr( | 1570 Definition* result = new (Z) InstanceCallInstr( |
1634 node->token_pos(), | 1571 node->token_pos(), |
1635 Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), | 1572 Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(), |
1636 node->kind(), | |
1637 arguments, | 1573 arguments, |
1638 Object::null_array(), // No argument names. | 1574 Object::null_array(), // No argument names. |
1639 kNumArgsChecked, | 1575 kNumArgsChecked, owner()->ic_data_array()); |
1640 owner()->ic_data_array()); | |
1641 if (negate_result) { | 1576 if (negate_result) { |
1642 result = new(Z) BooleanNegateInstr(Bind(result)); | 1577 result = new (Z) BooleanNegateInstr(Bind(result)); |
1643 } | 1578 } |
1644 ReturnDefinition(result); | 1579 ReturnDefinition(result); |
1645 return; | 1580 return; |
1646 } | 1581 } |
1647 | 1582 |
1648 PushArgumentInstr* push_type_args = NULL; | 1583 PushArgumentInstr* push_type_args = NULL; |
1649 if (type.IsInstantiated()) { | 1584 if (type.IsInstantiated()) { |
1650 push_type_args = PushArgument(BuildNullValue(node->token_pos())); | 1585 push_type_args = PushArgument(BuildNullValue(node->token_pos())); |
1651 } else { | 1586 } else { |
1652 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); | 1587 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); |
1653 } | 1588 } |
1654 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1589 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1655 new(Z) ZoneGrowableArray<PushArgumentInstr*>(4); | 1590 new (Z) ZoneGrowableArray<PushArgumentInstr*>(4); |
1656 arguments->Add(push_left); | 1591 arguments->Add(push_left); |
1657 arguments->Add(push_type_args); | 1592 arguments->Add(push_type_args); |
1658 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1593 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
1659 Value* type_const = Bind(new(Z) ConstantInstr(type)); | 1594 Value* type_const = Bind(new (Z) ConstantInstr(type)); |
1660 arguments->Add(PushArgument(type_const)); | 1595 arguments->Add(PushArgument(type_const)); |
1661 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); | 1596 const Bool& negate = Bool::Get(node->kind() == Token::kISNOT); |
1662 Value* negate_arg = Bind(new(Z) ConstantInstr(negate)); | 1597 Value* negate_arg = Bind(new (Z) ConstantInstr(negate)); |
1663 arguments->Add(PushArgument(negate_arg)); | 1598 arguments->Add(PushArgument(negate_arg)); |
1664 const intptr_t kNumArgsChecked = 1; | 1599 const intptr_t kNumArgsChecked = 1; |
1665 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 1600 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1666 node->token_pos(), | 1601 node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()), |
1667 Library::PrivateCoreLibName(Symbols::_instanceOf()), | 1602 node->kind(), arguments, |
1668 node->kind(), | |
1669 arguments, | |
1670 Object::null_array(), // No argument names. | 1603 Object::null_array(), // No argument names. |
1671 kNumArgsChecked, | 1604 kNumArgsChecked, owner()->ic_data_array()); |
1672 owner()->ic_data_array()); | |
1673 ReturnDefinition(call); | 1605 ReturnDefinition(call); |
1674 } | 1606 } |
1675 | 1607 |
1676 | 1608 |
1677 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { | 1609 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { |
1678 ASSERT(Token::IsTypeCastOperator(node->kind())); | 1610 ASSERT(Token::IsTypeCastOperator(node->kind())); |
1679 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); | 1611 ASSERT(!node->right()->AsTypeNode()->type().IsNull()); |
1680 const AbstractType& type = node->right()->AsTypeNode()->type(); | 1612 const AbstractType& type = node->right()->AsTypeNode()->type(); |
1681 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); | 1613 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
1682 ValueGraphVisitor for_value(owner()); | 1614 ValueGraphVisitor for_value(owner()); |
1683 node->left()->Visit(&for_value); | 1615 node->left()->Visit(&for_value); |
1684 Append(for_value); | 1616 Append(for_value); |
1685 if (CanSkipTypeCheck(node->token_pos(), | 1617 if (CanSkipTypeCheck(node->token_pos(), for_value.value(), type, |
1686 for_value.value(), | |
1687 type, | |
1688 Symbols::InTypeCast())) { | 1618 Symbols::InTypeCast())) { |
1689 ReturnValue(for_value.value()); | 1619 ReturnValue(for_value.value()); |
1690 return; | 1620 return; |
1691 } | 1621 } |
1692 PushArgumentInstr* push_left = PushArgument(for_value.value()); | 1622 PushArgumentInstr* push_left = PushArgument(for_value.value()); |
1693 PushArgumentInstr* push_type_args = NULL; | 1623 PushArgumentInstr* push_type_args = NULL; |
1694 if (type.IsInstantiated()) { | 1624 if (type.IsInstantiated()) { |
1695 push_type_args = PushArgument(BuildNullValue(node->token_pos())); | 1625 push_type_args = PushArgument(BuildNullValue(node->token_pos())); |
1696 } else { | 1626 } else { |
1697 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); | 1627 BuildTypecheckPushArguments(node->token_pos(), &push_type_args); |
1698 } | 1628 } |
1699 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1629 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1700 new(Z) ZoneGrowableArray<PushArgumentInstr*>(3); | 1630 new (Z) ZoneGrowableArray<PushArgumentInstr*>(3); |
1701 arguments->Add(push_left); | 1631 arguments->Add(push_left); |
1702 arguments->Add(push_type_args); | 1632 arguments->Add(push_type_args); |
1703 Value* type_arg = Bind(new(Z) ConstantInstr(type)); | 1633 Value* type_arg = Bind(new (Z) ConstantInstr(type)); |
1704 arguments->Add(PushArgument(type_arg)); | 1634 arguments->Add(PushArgument(type_arg)); |
1705 const intptr_t kNumArgsChecked = 1; | 1635 const intptr_t kNumArgsChecked = 1; |
1706 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 1636 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1707 node->token_pos(), | 1637 node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()), |
1708 Library::PrivateCoreLibName(Symbols::_as()), | 1638 node->kind(), arguments, |
1709 node->kind(), | |
1710 arguments, | |
1711 Object::null_array(), // No argument names. | 1639 Object::null_array(), // No argument names. |
1712 kNumArgsChecked, | 1640 kNumArgsChecked, owner()->ic_data_array()); |
1713 owner()->ic_data_array()); | |
1714 ReturnDefinition(call); | 1641 ReturnDefinition(call); |
1715 } | 1642 } |
1716 | 1643 |
1717 | 1644 |
1718 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare( | 1645 StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare( |
1719 AstNode* left, | 1646 AstNode* left, |
1720 AstNode* right, | 1647 AstNode* right, |
1721 Token::Kind kind, | 1648 Token::Kind kind, |
1722 TokenPosition token_pos) { | 1649 TokenPosition token_pos) { |
1723 ValueGraphVisitor for_left_value(owner()); | 1650 ValueGraphVisitor for_left_value(owner()); |
1724 left->Visit(&for_left_value); | 1651 left->Visit(&for_left_value); |
1725 Append(for_left_value); | 1652 Append(for_left_value); |
1726 ValueGraphVisitor for_right_value(owner()); | 1653 ValueGraphVisitor for_right_value(owner()); |
1727 right->Visit(&for_right_value); | 1654 right->Visit(&for_right_value); |
1728 Append(for_right_value); | 1655 Append(for_right_value); |
1729 StrictCompareInstr* comp = new(Z) StrictCompareInstr(token_pos, | 1656 StrictCompareInstr* comp = new (Z) StrictCompareInstr( |
1730 kind, | 1657 token_pos, kind, for_left_value.value(), for_right_value.value(), |
1731 for_left_value.value(), | 1658 true); // Number check. |
1732 for_right_value.value(), | |
1733 true); // Number check. | |
1734 return comp; | 1659 return comp; |
1735 } | 1660 } |
1736 | 1661 |
1737 | 1662 |
1738 // <Expression> :: Comparison { kind: Token::Kind | 1663 // <Expression> :: Comparison { kind: Token::Kind |
1739 // left: <Expression> | 1664 // left: <Expression> |
1740 // right: <Expression> } | 1665 // right: <Expression> } |
1741 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 1666 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
1742 if (Token::IsTypeTestOperator(node->kind())) { | 1667 if (Token::IsTypeTestOperator(node->kind())) { |
1743 BuildTypeTest(node); | 1668 BuildTypeTest(node); |
(...skipping 12 matching lines...) Expand all Loading... |
1756 } | 1681 } |
1757 | 1682 |
1758 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 1683 if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
1759 // Eagerly fold null-comparisons. | 1684 // Eagerly fold null-comparisons. |
1760 LiteralNode* left_lit = node->left()->AsLiteralNode(); | 1685 LiteralNode* left_lit = node->left()->AsLiteralNode(); |
1761 LiteralNode* right_lit = node->right()->AsLiteralNode(); | 1686 LiteralNode* right_lit = node->right()->AsLiteralNode(); |
1762 if (((left_lit != NULL) && left_lit->literal().IsNull()) || | 1687 if (((left_lit != NULL) && left_lit->literal().IsNull()) || |
1763 ((right_lit != NULL) && right_lit->literal().IsNull())) { | 1688 ((right_lit != NULL) && right_lit->literal().IsNull())) { |
1764 Token::Kind kind = | 1689 Token::Kind kind = |
1765 (node->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT; | 1690 (node->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT; |
1766 StrictCompareInstr* compare = | 1691 StrictCompareInstr* compare = BuildStrictCompare( |
1767 BuildStrictCompare(node->left(), node->right(), | 1692 node->left(), node->right(), kind, node->token_pos()); |
1768 kind, node->token_pos()); | |
1769 ReturnDefinition(compare); | 1693 ReturnDefinition(compare); |
1770 return; | 1694 return; |
1771 } | 1695 } |
1772 | 1696 |
1773 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1697 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1774 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1698 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1775 | 1699 |
1776 ValueGraphVisitor for_left_value(owner()); | 1700 ValueGraphVisitor for_left_value(owner()); |
1777 node->left()->Visit(&for_left_value); | 1701 node->left()->Visit(&for_left_value); |
1778 Append(for_left_value); | 1702 Append(for_left_value); |
1779 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1703 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1780 arguments->Add(push_left); | 1704 arguments->Add(push_left); |
1781 | 1705 |
1782 ValueGraphVisitor for_right_value(owner()); | 1706 ValueGraphVisitor for_right_value(owner()); |
1783 node->right()->Visit(&for_right_value); | 1707 node->right()->Visit(&for_right_value); |
1784 Append(for_right_value); | 1708 Append(for_right_value); |
1785 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1709 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
1786 arguments->Add(push_right); | 1710 arguments->Add(push_right); |
1787 | 1711 |
1788 const intptr_t kNumArgsChecked = 2; | 1712 const intptr_t kNumArgsChecked = 2; |
1789 Definition* result = new(Z) InstanceCallInstr( | 1713 Definition* result = new (Z) |
1790 node->token_pos(), | 1714 InstanceCallInstr(node->token_pos(), Symbols::EqualOperator(), |
1791 Symbols::EqualOperator(), | 1715 Token::kEQ, // Result is negated later for kNE. |
1792 Token::kEQ, // Result is negated later for kNE. | 1716 arguments, Object::null_array(), kNumArgsChecked, |
1793 arguments, | 1717 owner()->ic_data_array()); |
1794 Object::null_array(), | |
1795 kNumArgsChecked, | |
1796 owner()->ic_data_array()); | |
1797 if (node->kind() == Token::kNE) { | 1718 if (node->kind() == Token::kNE) { |
1798 Isolate* isolate = Isolate::Current(); | 1719 Isolate* isolate = Isolate::Current(); |
1799 if (isolate->type_checks() || isolate->asserts()) { | 1720 if (isolate->type_checks() || isolate->asserts()) { |
1800 Value* value = Bind(result); | 1721 Value* value = Bind(result); |
1801 result = new(Z) AssertBooleanInstr(node->token_pos(), value); | 1722 result = new (Z) AssertBooleanInstr(node->token_pos(), value); |
1802 } | 1723 } |
1803 Value* value = Bind(result); | 1724 Value* value = Bind(result); |
1804 result = new(Z) BooleanNegateInstr(value); | 1725 result = new (Z) BooleanNegateInstr(value); |
1805 } | 1726 } |
1806 ReturnDefinition(result); | 1727 ReturnDefinition(result); |
1807 return; | 1728 return; |
1808 } | 1729 } |
1809 | 1730 |
1810 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1731 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1811 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 1732 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
1812 | 1733 |
1813 ValueGraphVisitor for_left_value(owner()); | 1734 ValueGraphVisitor for_left_value(owner()); |
1814 node->left()->Visit(&for_left_value); | 1735 node->left()->Visit(&for_left_value); |
1815 Append(for_left_value); | 1736 Append(for_left_value); |
1816 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); | 1737 PushArgumentInstr* push_left = PushArgument(for_left_value.value()); |
1817 arguments->Add(push_left); | 1738 arguments->Add(push_left); |
1818 | 1739 |
1819 ValueGraphVisitor for_right_value(owner()); | 1740 ValueGraphVisitor for_right_value(owner()); |
1820 node->right()->Visit(&for_right_value); | 1741 node->right()->Visit(&for_right_value); |
1821 Append(for_right_value); | 1742 Append(for_right_value); |
1822 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); | 1743 PushArgumentInstr* push_right = PushArgument(for_right_value.value()); |
1823 arguments->Add(push_right); | 1744 arguments->Add(push_right); |
1824 | 1745 |
1825 ASSERT(Token::IsRelationalOperator(node->kind())); | 1746 ASSERT(Token::IsRelationalOperator(node->kind())); |
1826 InstanceCallInstr* comp = new(Z) InstanceCallInstr( | 1747 InstanceCallInstr* comp = new (Z) InstanceCallInstr( |
1827 node->token_pos(), | 1748 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, |
1828 Symbols::Token(node->kind()), | 1749 Object::null_array(), 2, owner()->ic_data_array()); |
1829 node->kind(), | |
1830 arguments, | |
1831 Object::null_array(), | |
1832 2, | |
1833 owner()->ic_data_array()); | |
1834 ReturnDefinition(comp); | 1750 ReturnDefinition(comp); |
1835 } | 1751 } |
1836 | 1752 |
1837 | 1753 |
1838 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { | 1754 void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) { |
1839 // "!" cannot be overloaded, therefore do not call operator. | 1755 // "!" cannot be overloaded, therefore do not call operator. |
1840 if (node->kind() == Token::kNOT) { | 1756 if (node->kind() == Token::kNOT) { |
1841 ValueGraphVisitor for_value(owner()); | 1757 ValueGraphVisitor for_value(owner()); |
1842 node->operand()->Visit(&for_value); | 1758 node->operand()->Visit(&for_value); |
1843 Append(for_value); | 1759 Append(for_value); |
1844 Value* value = for_value.value(); | 1760 Value* value = for_value.value(); |
1845 Isolate* isolate = Isolate::Current(); | 1761 Isolate* isolate = Isolate::Current(); |
1846 if (isolate->type_checks() || isolate->asserts()) { | 1762 if (isolate->type_checks() || isolate->asserts()) { |
1847 value = | 1763 value = |
1848 Bind(new(Z) AssertBooleanInstr(node->operand()->token_pos(), value)); | 1764 Bind(new (Z) AssertBooleanInstr(node->operand()->token_pos(), value)); |
1849 } | 1765 } |
1850 BooleanNegateInstr* negate = new(Z) BooleanNegateInstr(value); | 1766 BooleanNegateInstr* negate = new (Z) BooleanNegateInstr(value); |
1851 ReturnDefinition(negate); | 1767 ReturnDefinition(negate); |
1852 return; | 1768 return; |
1853 } | 1769 } |
1854 | 1770 |
1855 ValueGraphVisitor for_value(owner()); | 1771 ValueGraphVisitor for_value(owner()); |
1856 node->operand()->Visit(&for_value); | 1772 node->operand()->Visit(&for_value); |
1857 Append(for_value); | 1773 Append(for_value); |
1858 PushArgumentInstr* push_value = PushArgument(for_value.value()); | 1774 PushArgumentInstr* push_value = PushArgument(for_value.value()); |
1859 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 1775 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
1860 new(Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 1776 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
1861 arguments->Add(push_value); | 1777 arguments->Add(push_value); |
1862 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 1778 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
1863 node->token_pos(), | 1779 node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments, |
1864 Symbols::Token(node->kind()), | 1780 Object::null_array(), 1, owner()->ic_data_array()); |
1865 node->kind(), | |
1866 arguments, | |
1867 Object::null_array(), | |
1868 1, | |
1869 owner()->ic_data_array()); | |
1870 ReturnDefinition(call); | 1781 ReturnDefinition(call); |
1871 } | 1782 } |
1872 | 1783 |
1873 | 1784 |
1874 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 1785 void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
1875 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1786 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
1876 node->condition()->Visit(&for_test); | 1787 node->condition()->Visit(&for_test); |
1877 | 1788 |
1878 // Translate the subexpressions for their effects. | 1789 // Translate the subexpressions for their effects. |
1879 EffectGraphVisitor for_true(owner()); | 1790 EffectGraphVisitor for_true(owner()); |
1880 node->true_expr()->Visit(&for_true); | 1791 node->true_expr()->Visit(&for_true); |
1881 EffectGraphVisitor for_false(owner()); | 1792 EffectGraphVisitor for_false(owner()); |
1882 node->false_expr()->Visit(&for_false); | 1793 node->false_expr()->Visit(&for_false); |
1883 | 1794 |
1884 Join(for_test, for_true, for_false); | 1795 Join(for_test, for_true, for_false); |
1885 } | 1796 } |
1886 | 1797 |
1887 | 1798 |
1888 void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { | 1799 void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) { |
1889 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1800 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
1890 node->condition()->Visit(&for_test); | 1801 node->condition()->Visit(&for_test); |
1891 | 1802 |
1892 ValueGraphVisitor for_true(owner()); | 1803 ValueGraphVisitor for_true(owner()); |
1893 node->true_expr()->Visit(&for_true); | 1804 node->true_expr()->Visit(&for_true); |
1894 ASSERT(for_true.is_open()); | 1805 ASSERT(for_true.is_open()); |
1895 for_true.Do(BuildStoreExprTemp(for_true.value(), | 1806 for_true.Do( |
1896 node->true_expr()->token_pos())); | 1807 BuildStoreExprTemp(for_true.value(), node->true_expr()->token_pos())); |
1897 | 1808 |
1898 ValueGraphVisitor for_false(owner()); | 1809 ValueGraphVisitor for_false(owner()); |
1899 node->false_expr()->Visit(&for_false); | 1810 node->false_expr()->Visit(&for_false); |
1900 ASSERT(for_false.is_open()); | 1811 ASSERT(for_false.is_open()); |
1901 for_false.Do(BuildStoreExprTemp(for_false.value(), | 1812 for_false.Do( |
1902 node->false_expr()->token_pos())); | 1813 BuildStoreExprTemp(for_false.value(), node->false_expr()->token_pos())); |
1903 | 1814 |
1904 Join(for_test, for_true, for_false); | 1815 Join(for_test, for_true, for_false); |
1905 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); | 1816 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); |
1906 } | 1817 } |
1907 | 1818 |
1908 | 1819 |
1909 // <Statement> ::= If { condition: <Expression> | 1820 // <Statement> ::= If { condition: <Expression> |
1910 // true_branch: <Sequence> | 1821 // true_branch: <Sequence> |
1911 // false_branch: <Sequence> } | 1822 // false_branch: <Sequence> } |
1912 void EffectGraphVisitor::VisitIfNode(IfNode* node) { | 1823 void EffectGraphVisitor::VisitIfNode(IfNode* node) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1957 // | 1868 // |
1958 // Note: The specification of switch/case is under discussion and may change | 1869 // Note: The specification of switch/case is under discussion and may change |
1959 // drastically. | 1870 // drastically. |
1960 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { | 1871 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
1961 const intptr_t len = node->case_expressions()->length(); | 1872 const intptr_t len = node->case_expressions()->length(); |
1962 // Create case statements instructions. | 1873 // Create case statements instructions. |
1963 EffectGraphVisitor for_case_statements(owner()); | 1874 EffectGraphVisitor for_case_statements(owner()); |
1964 // Compute the start of the statements fragment. | 1875 // Compute the start of the statements fragment. |
1965 JoinEntryInstr* statement_start = NULL; | 1876 JoinEntryInstr* statement_start = NULL; |
1966 if (node->label() == NULL) { | 1877 if (node->label() == NULL) { |
1967 statement_start = new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 1878 statement_start = new (Z) |
1968 owner()->try_index()); | 1879 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
1969 } else { | 1880 } else { |
1970 // The case nodes are nested inside a SequenceNode that is the body of a | 1881 // The case nodes are nested inside a SequenceNode that is the body of a |
1971 // SwitchNode. The SwitchNode on the nesting stack contains the | 1882 // SwitchNode. The SwitchNode on the nesting stack contains the |
1972 // continue labels for all the case clauses. | 1883 // continue labels for all the case clauses. |
1973 statement_start = | 1884 statement_start = |
1974 owner()->nesting_stack()->outer()->ContinueTargetFor(node->label()); | 1885 owner()->nesting_stack()->outer()->ContinueTargetFor(node->label()); |
1975 } | 1886 } |
1976 ASSERT(statement_start != NULL); | 1887 ASSERT(statement_start != NULL); |
1977 node->statements()->Visit(&for_case_statements); | 1888 node->statements()->Visit(&for_case_statements); |
1978 Instruction* statement_exit = | 1889 Instruction* statement_exit = |
(...skipping 30 matching lines...) Expand all Loading... |
2009 // Handle last (or only) case: false goes to exit or to statement if this | 1920 // Handle last (or only) case: false goes to exit or to statement if this |
2010 // node contains default. | 1921 // node contains default. |
2011 if (len > 0) { | 1922 if (len > 0) { |
2012 ASSERT(next_target != NULL); | 1923 ASSERT(next_target != NULL); |
2013 if (node->contains_default()) { | 1924 if (node->contains_default()) { |
2014 // True and false go to statement start. | 1925 // True and false go to statement start. |
2015 next_target->Goto(statement_start); | 1926 next_target->Goto(statement_start); |
2016 exit_instruction = statement_exit; | 1927 exit_instruction = statement_exit; |
2017 } else { | 1928 } else { |
2018 if (statement_exit != NULL) { | 1929 if (statement_exit != NULL) { |
2019 JoinEntryInstr* join = new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 1930 JoinEntryInstr* join = new (Z) |
2020 owner()->try_index()); | 1931 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
2021 statement_exit->Goto(join); | 1932 statement_exit->Goto(join); |
2022 next_target->Goto(join); | 1933 next_target->Goto(join); |
2023 exit_instruction = join; | 1934 exit_instruction = join; |
2024 } else { | 1935 } else { |
2025 exit_instruction = next_target; | 1936 exit_instruction = next_target; |
2026 } | 1937 } |
2027 } | 1938 } |
2028 } else { | 1939 } else { |
2029 // A CaseNode without case expressions must contain default. | 1940 // A CaseNode without case expressions must contain default. |
2030 ASSERT(node->contains_default()); | 1941 ASSERT(node->contains_default()); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2093 // Traverse the body first in order to generate continue and break labels. | 2004 // Traverse the body first in order to generate continue and break labels. |
2094 EffectGraphVisitor for_body(owner()); | 2005 EffectGraphVisitor for_body(owner()); |
2095 node->body()->Visit(&for_body); | 2006 node->body()->Visit(&for_body); |
2096 | 2007 |
2097 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 2008 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
2098 node->condition()->Visit(&for_test); | 2009 node->condition()->Visit(&for_test); |
2099 ASSERT(is_open()); | 2010 ASSERT(is_open()); |
2100 | 2011 |
2101 // Tie do-while loop (test is after the body). | 2012 // Tie do-while loop (test is after the body). |
2102 JoinEntryInstr* body_entry_join = | 2013 JoinEntryInstr* body_entry_join = |
2103 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 2014 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
2104 owner()->try_index()); | |
2105 Goto(body_entry_join); | 2015 Goto(body_entry_join); |
2106 Instruction* body_exit = AppendFragment(body_entry_join, for_body); | 2016 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
2107 | 2017 |
2108 JoinEntryInstr* join = nested_loop.continue_target(); | 2018 JoinEntryInstr* join = nested_loop.continue_target(); |
2109 if ((body_exit != NULL) || (join != NULL)) { | 2019 if ((body_exit != NULL) || (join != NULL)) { |
2110 if (join == NULL) { | 2020 if (join == NULL) { |
2111 join = new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 2021 join = new (Z) |
2112 owner()->try_index()); | 2022 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
2113 } | 2023 } |
2114 CheckStackOverflowInstr* check = new(Z) CheckStackOverflowInstr( | 2024 CheckStackOverflowInstr* check = new (Z) |
2115 node->token_pos(), owner()->loop_depth()); | 2025 CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()); |
2116 join->LinkTo(check); | 2026 join->LinkTo(check); |
2117 check->LinkTo(for_test.entry()); | 2027 check->LinkTo(for_test.entry()); |
2118 if (body_exit != NULL) { | 2028 if (body_exit != NULL) { |
2119 body_exit->Goto(join); | 2029 body_exit->Goto(join); |
2120 } | 2030 } |
2121 } | 2031 } |
2122 | 2032 |
2123 for_test.IfTrueGoto(body_entry_join); | 2033 for_test.IfTrueGoto(body_entry_join); |
2124 join = nested_loop.break_target(); | 2034 join = nested_loop.break_target(); |
2125 if (join == NULL) { | 2035 if (join == NULL) { |
(...skipping 27 matching lines...) Expand all Loading... |
2153 // Compose body to set any jump labels. | 2063 // Compose body to set any jump labels. |
2154 EffectGraphVisitor for_body(owner()); | 2064 EffectGraphVisitor for_body(owner()); |
2155 node->body()->Visit(&for_body); | 2065 node->body()->Visit(&for_body); |
2156 | 2066 |
2157 EffectGraphVisitor for_increment(owner()); | 2067 EffectGraphVisitor for_increment(owner()); |
2158 node->increment()->Visit(&for_increment); | 2068 node->increment()->Visit(&for_increment); |
2159 | 2069 |
2160 // Join the loop body and increment and then tie the loop. | 2070 // Join the loop body and increment and then tie the loop. |
2161 JoinEntryInstr* continue_join = nested_loop.continue_target(); | 2071 JoinEntryInstr* continue_join = nested_loop.continue_target(); |
2162 if ((continue_join != NULL) || for_body.is_open()) { | 2072 if ((continue_join != NULL) || for_body.is_open()) { |
2163 JoinEntryInstr* loop_entry = | 2073 JoinEntryInstr* loop_entry = new (Z) |
2164 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 2074 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
2165 if (continue_join != NULL) { | 2075 if (continue_join != NULL) { |
2166 if (for_body.is_open()) for_body.Goto(continue_join); | 2076 if (for_body.is_open()) for_body.Goto(continue_join); |
2167 Instruction* current = AppendFragment(continue_join, for_increment); | 2077 Instruction* current = AppendFragment(continue_join, for_increment); |
2168 current->Goto(loop_entry); | 2078 current->Goto(loop_entry); |
2169 } else { | 2079 } else { |
2170 for_body.Append(for_increment); | 2080 for_body.Append(for_increment); |
2171 for_body.Goto(loop_entry); | 2081 for_body.Goto(loop_entry); |
2172 } | 2082 } |
2173 Goto(loop_entry); | 2083 Goto(loop_entry); |
2174 exit_ = loop_entry; | 2084 exit_ = loop_entry; |
2175 // Note: the stack overflow check happens on the back branch that jumps | 2085 // Note: the stack overflow check happens on the back branch that jumps |
2176 // to the increment instruction. The token position for the overflow | 2086 // to the increment instruction. The token position for the overflow |
2177 // check must match the position of the increment expression, so that | 2087 // check must match the position of the increment expression, so that |
2178 // the context level (if any) matches the that of the increment | 2088 // the context level (if any) matches the that of the increment |
2179 // expression. | 2089 // expression. |
2180 AddInstruction( | 2090 AddInstruction(new (Z) CheckStackOverflowInstr( |
2181 new(Z) CheckStackOverflowInstr(node->increment()->token_pos(), | 2091 node->increment()->token_pos(), owner()->loop_depth())); |
2182 owner()->loop_depth())); | |
2183 } | 2092 } |
2184 | 2093 |
2185 if (node->condition() == NULL) { | 2094 if (node->condition() == NULL) { |
2186 // Endless loop, no test. | 2095 // Endless loop, no test. |
2187 Append(for_body); | 2096 Append(for_body); |
2188 exit_ = nested_loop.break_target(); // May be NULL. | 2097 exit_ = nested_loop.break_target(); // May be NULL. |
2189 } else { | 2098 } else { |
2190 EffectGraphVisitor for_test_preamble(owner()); | 2099 EffectGraphVisitor for_test_preamble(owner()); |
2191 if (node->condition_preamble() != NULL) { | 2100 if (node->condition_preamble() != NULL) { |
2192 node->condition_preamble()->Visit(&for_test_preamble); | 2101 node->condition_preamble()->Visit(&for_test_preamble); |
(...skipping 30 matching lines...) Expand all Loading... |
2223 // Unchain the context(s) up to the outer context level of the scope which | 2132 // Unchain the context(s) up to the outer context level of the scope which |
2224 // contains the destination label. | 2133 // contains the destination label. |
2225 SourceLabel* label = node->label(); | 2134 SourceLabel* label = node->label(); |
2226 ASSERT(label->owner() != NULL); | 2135 ASSERT(label->owner() != NULL); |
2227 AdjustContextLevel(label->owner()); | 2136 AdjustContextLevel(label->owner()); |
2228 | 2137 |
2229 JoinEntryInstr* jump_target = NULL; | 2138 JoinEntryInstr* jump_target = NULL; |
2230 NestedStatement* current = owner()->nesting_stack(); | 2139 NestedStatement* current = owner()->nesting_stack(); |
2231 while (current != NULL) { | 2140 while (current != NULL) { |
2232 jump_target = (node->kind() == Token::kBREAK) | 2141 jump_target = (node->kind() == Token::kBREAK) |
2233 ? current->BreakTargetFor(node->label()) | 2142 ? current->BreakTargetFor(node->label()) |
2234 : current->ContinueTargetFor(node->label()); | 2143 : current->ContinueTargetFor(node->label()); |
2235 if (jump_target != NULL) break; | 2144 if (jump_target != NULL) break; |
2236 current = current->outer(); | 2145 current = current->outer(); |
2237 } | 2146 } |
2238 ASSERT(jump_target != NULL); | 2147 ASSERT(jump_target != NULL); |
2239 Goto(jump_target); | 2148 Goto(jump_target); |
2240 } | 2149 } |
2241 | 2150 |
2242 | 2151 |
2243 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { | 2152 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
2244 UNREACHABLE(); | 2153 UNREACHABLE(); |
2245 } | 2154 } |
2246 | 2155 |
2247 | 2156 |
2248 void EffectGraphVisitor::VisitAwaitNode(AwaitNode* node) { | 2157 void EffectGraphVisitor::VisitAwaitNode(AwaitNode* node) { |
2249 // Await nodes are temporary during parsing. | 2158 // Await nodes are temporary during parsing. |
2250 UNREACHABLE(); | 2159 UNREACHABLE(); |
2251 } | 2160 } |
2252 | 2161 |
2253 | 2162 |
2254 void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) { | 2163 void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) { |
2255 // We need to create a new await state which involves: | 2164 // We need to create a new await state which involves: |
2256 // * Increase the jump counter. Sanity check against the list of targets. | 2165 // * Increase the jump counter. Sanity check against the list of targets. |
2257 // * Save the current context for resuming. | 2166 // * Save the current context for resuming. |
2258 ASSERT(node->token_pos().IsSynthetic() || node->token_pos().IsNoSource()); | 2167 ASSERT(node->token_pos().IsSynthetic() || node->token_pos().IsNoSource()); |
2259 ASSERT(node->async_scope() != NULL); | 2168 ASSERT(node->async_scope() != NULL); |
2260 ASSERT(node->await_scope() != NULL); | 2169 ASSERT(node->await_scope() != NULL); |
2261 LocalVariable* jump_var = node->async_scope()->LookupVariable( | 2170 LocalVariable* jump_var = |
2262 Symbols::AwaitJumpVar(), false); | 2171 node->async_scope()->LookupVariable(Symbols::AwaitJumpVar(), false); |
2263 LocalVariable* ctx_var = node->async_scope()->LookupVariable( | 2172 LocalVariable* ctx_var = |
2264 Symbols::AwaitContextVar(), false); | 2173 node->async_scope()->LookupVariable(Symbols::AwaitContextVar(), false); |
2265 ASSERT((jump_var != NULL) && jump_var->is_captured()); | 2174 ASSERT((jump_var != NULL) && jump_var->is_captured()); |
2266 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); | 2175 ASSERT((ctx_var != NULL) && ctx_var->is_captured()); |
2267 const intptr_t jump_count = owner()->next_await_counter(); | 2176 const intptr_t jump_count = owner()->next_await_counter(); |
2268 ASSERT(jump_count >= 0); | 2177 ASSERT(jump_count >= 0); |
2269 // Sanity check that we always add a JoinEntryInstr before adding a new | 2178 // Sanity check that we always add a JoinEntryInstr before adding a new |
2270 // state. | 2179 // state. |
2271 ASSERT(jump_count == owner()->await_joins()->length()); | 2180 ASSERT(jump_count == owner()->await_joins()->length()); |
2272 // Store the counter in :await_jump_var. | 2181 // Store the counter in :await_jump_var. |
2273 Value* jump_val = Bind(new(Z) ConstantInstr( | 2182 Value* jump_val = Bind(new (Z) ConstantInstr( |
2274 Smi::ZoneHandle(Z, Smi::New(jump_count)), node->token_pos())); | 2183 Smi::ZoneHandle(Z, Smi::New(jump_count)), node->token_pos())); |
2275 Do(BuildStoreLocal(*jump_var, jump_val, node->token_pos())); | 2184 Do(BuildStoreLocal(*jump_var, jump_val, node->token_pos())); |
2276 // Save the current context for resuming. | 2185 // Save the current context for resuming. |
2277 BuildSaveContext(*ctx_var, node->token_pos()); | 2186 BuildSaveContext(*ctx_var, node->token_pos()); |
2278 } | 2187 } |
2279 | 2188 |
2280 | 2189 |
2281 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { | 2190 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { |
2282 return kFirstLocalSlotFromFp | 2191 return kFirstLocalSlotFromFp - owner()->num_stack_locals() - |
2283 - owner()->num_stack_locals() | 2192 owner()->num_copied_params() - owner()->args_pushed() - |
2284 - owner()->num_copied_params() | 2193 owner()->temp_count() + 1; |
2285 - owner()->args_pushed() | |
2286 - owner()->temp_count() + 1; | |
2287 } | 2194 } |
2288 | 2195 |
2289 | 2196 |
2290 LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) { | 2197 LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) { |
2291 ASSERT(value->definition()->temp_index() == (owner()->temp_count() - 1)); | 2198 ASSERT(value->definition()->temp_index() == (owner()->temp_count() - 1)); |
2292 intptr_t index = GetCurrentTempLocalIndex(); | 2199 intptr_t index = GetCurrentTempLocalIndex(); |
2293 char name[64]; | 2200 char name[64]; |
2294 OS::SNPrint(name, 64, ":tmp_local%" Pd, index); | 2201 OS::SNPrint(name, 64, ":tmp_local%" Pd, index); |
2295 LocalVariable* var = | 2202 LocalVariable* var = |
2296 new(Z) LocalVariable(TokenPosition::kNoSource, | 2203 new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
2297 TokenPosition::kNoSource, | 2204 String::ZoneHandle(Z, Symbols::New(T, name)), |
2298 String::ZoneHandle(Z, Symbols::New(T, name)), | 2205 *value->Type()->ToAbstractType()); |
2299 *value->Type()->ToAbstractType()); | |
2300 var->set_index(index); | 2206 var->set_index(index); |
2301 return var; | 2207 return var; |
2302 } | 2208 } |
2303 | 2209 |
2304 | 2210 |
2305 Definition* EffectGraphVisitor::ExitTempLocalScope(Value* value) { | 2211 Definition* EffectGraphVisitor::ExitTempLocalScope(Value* value) { |
2306 return new(Z) DropTempsInstr(0, value); | 2212 return new (Z) DropTempsInstr(0, value); |
2307 } | 2213 } |
2308 | 2214 |
2309 | 2215 |
2310 void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) { | 2216 void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) { |
2311 intptr_t num_temps = node->num_temps(); | 2217 intptr_t num_temps = node->num_temps(); |
2312 for (intptr_t i = 0; i < num_temps; ++i) { | 2218 for (intptr_t i = 0; i < num_temps; ++i) { |
2313 ValueGraphVisitor for_value(owner()); | 2219 ValueGraphVisitor for_value(owner()); |
2314 node->InitializerAt(i)->Visit(&for_value); | 2220 node->InitializerAt(i)->Visit(&for_value); |
2315 Append(for_value); | 2221 Append(for_value); |
2316 ASSERT(!node->TempAt(i)->HasIndex() || | 2222 ASSERT(!node->TempAt(i)->HasIndex() || |
2317 (node->TempAt(i)->index() == GetCurrentTempLocalIndex())); | 2223 (node->TempAt(i)->index() == GetCurrentTempLocalIndex())); |
2318 node->TempAt(i)->set_index(GetCurrentTempLocalIndex()); | 2224 node->TempAt(i)->set_index(GetCurrentTempLocalIndex()); |
2319 } | 2225 } |
2320 } | 2226 } |
2321 | 2227 |
2322 | 2228 |
2323 void EffectGraphVisitor::VisitLetNode(LetNode* node) { | 2229 void EffectGraphVisitor::VisitLetNode(LetNode* node) { |
2324 BuildLetTempExpressions(node); | 2230 BuildLetTempExpressions(node); |
2325 | 2231 |
2326 // Visit body. | 2232 // Visit body. |
2327 for (intptr_t i = 0; i < node->nodes().length(); ++i) { | 2233 for (intptr_t i = 0; i < node->nodes().length(); ++i) { |
2328 EffectGraphVisitor for_effect(owner()); | 2234 EffectGraphVisitor for_effect(owner()); |
2329 node->nodes()[i]->Visit(&for_effect); | 2235 node->nodes()[i]->Visit(&for_effect); |
2330 Append(for_effect); | 2236 Append(for_effect); |
2331 } | 2237 } |
2332 | 2238 |
2333 intptr_t num_temps = node->num_temps(); | 2239 intptr_t num_temps = node->num_temps(); |
2334 if (num_temps > 0) { | 2240 if (num_temps > 0) { |
2335 owner()->DeallocateTemps(num_temps); | 2241 owner()->DeallocateTemps(num_temps); |
2336 Do(new(Z) DropTempsInstr(num_temps, NULL)); | 2242 Do(new (Z) DropTempsInstr(num_temps, NULL)); |
2337 } | 2243 } |
2338 } | 2244 } |
2339 | 2245 |
2340 | 2246 |
2341 void ValueGraphVisitor::VisitLetNode(LetNode* node) { | 2247 void ValueGraphVisitor::VisitLetNode(LetNode* node) { |
2342 BuildLetTempExpressions(node); | 2248 BuildLetTempExpressions(node); |
2343 | 2249 |
2344 // Visit body. | 2250 // Visit body. |
2345 for (intptr_t i = 0; i < node->nodes().length() - 1; ++i) { | 2251 for (intptr_t i = 0; i < node->nodes().length() - 1; ++i) { |
2346 EffectGraphVisitor for_effect(owner()); | 2252 EffectGraphVisitor for_effect(owner()); |
2347 node->nodes()[i]->Visit(&for_effect); | 2253 node->nodes()[i]->Visit(&for_effect); |
2348 Append(for_effect); | 2254 Append(for_effect); |
2349 } | 2255 } |
2350 // Visit the last body expression for value. | 2256 // Visit the last body expression for value. |
2351 ValueGraphVisitor for_value(owner()); | 2257 ValueGraphVisitor for_value(owner()); |
2352 node->nodes().Last()->Visit(&for_value); | 2258 node->nodes().Last()->Visit(&for_value); |
2353 Append(for_value); | 2259 Append(for_value); |
2354 Value* result_value = for_value.value(); | 2260 Value* result_value = for_value.value(); |
2355 | 2261 |
2356 intptr_t num_temps = node->num_temps(); | 2262 intptr_t num_temps = node->num_temps(); |
2357 if (num_temps > 0) { | 2263 if (num_temps > 0) { |
2358 owner()->DeallocateTemps(num_temps); | 2264 owner()->DeallocateTemps(num_temps); |
2359 ReturnDefinition(new(Z) DropTempsInstr(num_temps, result_value)); | 2265 ReturnDefinition(new (Z) DropTempsInstr(num_temps, result_value)); |
2360 } else { | 2266 } else { |
2361 ReturnValue(result_value); | 2267 ReturnValue(result_value); |
2362 } | 2268 } |
2363 } | 2269 } |
2364 | 2270 |
2365 | 2271 |
2366 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { | 2272 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
2367 const TypeArguments& type_args = | 2273 const TypeArguments& type_args = |
2368 TypeArguments::ZoneHandle(Z, node->type().arguments()); | 2274 TypeArguments::ZoneHandle(Z, node->type().arguments()); |
2369 Value* element_type = BuildInstantiatedTypeArguments(node->token_pos(), | 2275 Value* element_type = |
2370 type_args); | 2276 BuildInstantiatedTypeArguments(node->token_pos(), type_args); |
2371 Value* num_elements = | 2277 Value* num_elements = |
2372 Bind(new(Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length())))); | 2278 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length())))); |
2373 CreateArrayInstr* create = new(Z) CreateArrayInstr(node->token_pos(), | 2279 CreateArrayInstr* create = |
2374 element_type, | 2280 new (Z) CreateArrayInstr(node->token_pos(), element_type, num_elements); |
2375 num_elements); | |
2376 Value* array_val = Bind(create); | 2281 Value* array_val = Bind(create); |
2377 | 2282 |
2378 { LocalVariable* tmp_var = EnterTempLocalScope(array_val); | 2283 { |
| 2284 LocalVariable* tmp_var = EnterTempLocalScope(array_val); |
2379 const intptr_t class_id = kArrayCid; | 2285 const intptr_t class_id = kArrayCid; |
2380 const intptr_t deopt_id = Thread::kNoDeoptId; | 2286 const intptr_t deopt_id = Thread::kNoDeoptId; |
2381 for (int i = 0; i < node->length(); ++i) { | 2287 for (int i = 0; i < node->length(); ++i) { |
2382 Value* array = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2288 Value* array = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
2383 Value* index = | 2289 Value* index = Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)), |
2384 Bind(new(Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)), | 2290 node->token_pos())); |
2385 node->token_pos())); | |
2386 ValueGraphVisitor for_value(owner()); | 2291 ValueGraphVisitor for_value(owner()); |
2387 node->ElementAt(i)->Visit(&for_value); | 2292 node->ElementAt(i)->Visit(&for_value); |
2388 Append(for_value); | 2293 Append(for_value); |
2389 // No store barrier needed for constants. | 2294 // No store barrier needed for constants. |
2390 const StoreBarrierType emit_store_barrier = | 2295 const StoreBarrierType emit_store_barrier = |
2391 for_value.value()->BindsToConstant() | 2296 for_value.value()->BindsToConstant() ? kNoStoreBarrier |
2392 ? kNoStoreBarrier | 2297 : kEmitStoreBarrier; |
2393 : kEmitStoreBarrier; | |
2394 const intptr_t index_scale = Instance::ElementSizeFor(class_id); | 2298 const intptr_t index_scale = Instance::ElementSizeFor(class_id); |
2395 StoreIndexedInstr* store = new(Z) StoreIndexedInstr( | 2299 StoreIndexedInstr* store = new (Z) StoreIndexedInstr( |
2396 array, index, for_value.value(), emit_store_barrier, | 2300 array, index, for_value.value(), emit_store_barrier, index_scale, |
2397 index_scale, class_id, kAlignedAccess, deopt_id, node->token_pos()); | 2301 class_id, kAlignedAccess, deopt_id, node->token_pos()); |
2398 Do(store); | 2302 Do(store); |
2399 } | 2303 } |
2400 ReturnDefinition(ExitTempLocalScope(array_val)); | 2304 ReturnDefinition(ExitTempLocalScope(array_val)); |
2401 } | 2305 } |
2402 } | 2306 } |
2403 | 2307 |
2404 | 2308 |
2405 void EffectGraphVisitor::VisitStringInterpolateNode( | 2309 void EffectGraphVisitor::VisitStringInterpolateNode( |
2406 StringInterpolateNode* node) { | 2310 StringInterpolateNode* node) { |
2407 ValueGraphVisitor for_argument(owner()); | 2311 ValueGraphVisitor for_argument(owner()); |
2408 ArrayNode* arguments = node->value(); | 2312 ArrayNode* arguments = node->value(); |
2409 if (arguments->length() == 1) { | 2313 if (arguments->length() == 1) { |
2410 ZoneGrowableArray<PushArgumentInstr*>* values = | 2314 ZoneGrowableArray<PushArgumentInstr*>* values = |
2411 new(Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 2315 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
2412 arguments->ElementAt(0)->Visit(&for_argument); | 2316 arguments->ElementAt(0)->Visit(&for_argument); |
2413 Append(for_argument); | 2317 Append(for_argument); |
2414 PushArgumentInstr* push_arg = PushArgument(for_argument.value()); | 2318 PushArgumentInstr* push_arg = PushArgument(for_argument.value()); |
2415 values->Add(push_arg); | 2319 values->Add(push_arg); |
2416 const int kNumberOfArguments = 1; | 2320 const int kNumberOfArguments = 1; |
2417 const Array& kNoArgumentNames = Object::null_array(); | 2321 const Array& kNoArgumentNames = Object::null_array(); |
2418 const Class& cls = | 2322 const Class& cls = |
2419 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); | 2323 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); |
2420 ASSERT(!cls.IsNull()); | 2324 ASSERT(!cls.IsNull()); |
2421 const Function& function = Function::ZoneHandle( | 2325 const Function& function = Function::ZoneHandle( |
2422 Z, | 2326 Z, Resolver::ResolveStatic( |
2423 Resolver::ResolveStatic( | 2327 cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()), |
2424 cls, | 2328 kNumberOfArguments, kNoArgumentNames)); |
2425 Library::PrivateCoreLibName(Symbols::InterpolateSingle()), | |
2426 kNumberOfArguments, | |
2427 kNoArgumentNames)); | |
2428 StaticCallInstr* call = | 2329 StaticCallInstr* call = |
2429 new(Z) StaticCallInstr(node->token_pos(), | 2330 new (Z) StaticCallInstr(node->token_pos(), function, kNoArgumentNames, |
2430 function, | 2331 values, owner()->ic_data_array()); |
2431 kNoArgumentNames, | |
2432 values, | |
2433 owner()->ic_data_array()); | |
2434 ReturnDefinition(call); | 2332 ReturnDefinition(call); |
2435 return; | 2333 return; |
2436 } | 2334 } |
2437 arguments->Visit(&for_argument); | 2335 arguments->Visit(&for_argument); |
2438 Append(for_argument); | 2336 Append(for_argument); |
2439 StringInterpolateInstr* instr = | 2337 StringInterpolateInstr* instr = |
2440 new(Z) StringInterpolateInstr(for_argument.value(), node->token_pos()); | 2338 new (Z) StringInterpolateInstr(for_argument.value(), node->token_pos()); |
2441 ReturnDefinition(instr); | 2339 ReturnDefinition(instr); |
2442 } | 2340 } |
2443 | 2341 |
2444 | 2342 |
2445 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { | 2343 void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) { |
2446 const Function& function = node->function(); | 2344 const Function& function = node->function(); |
2447 if (function.IsImplicitStaticClosureFunction()) { | 2345 if (function.IsImplicitStaticClosureFunction()) { |
2448 const Instance& closure = | 2346 const Instance& closure = |
2449 Instance::ZoneHandle(Z, function.ImplicitStaticClosure()); | 2347 Instance::ZoneHandle(Z, function.ImplicitStaticClosure()); |
2450 ReturnDefinition(new(Z) ConstantInstr(closure)); | 2348 ReturnDefinition(new (Z) ConstantInstr(closure)); |
2451 return; | 2349 return; |
2452 } | 2350 } |
2453 | 2351 |
2454 const bool is_implicit = function.IsImplicitInstanceClosureFunction(); | 2352 const bool is_implicit = function.IsImplicitInstanceClosureFunction(); |
2455 ASSERT(is_implicit || function.IsNonImplicitClosureFunction()); | 2353 ASSERT(is_implicit || function.IsNonImplicitClosureFunction()); |
2456 // The context scope may have already been set by the non-optimizing | 2354 // The context scope may have already been set by the non-optimizing |
2457 // compiler. If it was not, set it here. | 2355 // compiler. If it was not, set it here. |
2458 if (function.context_scope() == ContextScope::null()) { | 2356 if (function.context_scope() == ContextScope::null()) { |
2459 ASSERT(!is_implicit); | 2357 ASSERT(!is_implicit); |
2460 ASSERT(node->scope() != NULL); | 2358 ASSERT(node->scope() != NULL); |
2461 const ContextScope& context_scope = ContextScope::ZoneHandle( | 2359 const ContextScope& context_scope = ContextScope::ZoneHandle( |
2462 Z, node->scope()->PreserveOuterScope(owner()->context_level())); | 2360 Z, node->scope()->PreserveOuterScope(owner()->context_level())); |
2463 ASSERT(!function.HasCode()); | 2361 ASSERT(!function.HasCode()); |
2464 ASSERT(function.context_scope() == ContextScope::null()); | 2362 ASSERT(function.context_scope() == ContextScope::null()); |
2465 function.set_context_scope(context_scope); | 2363 function.set_context_scope(context_scope); |
2466 | 2364 |
2467 // The closure is now properly setup, add it to the lookup table. | 2365 // The closure is now properly setup, add it to the lookup table. |
2468 // It is possible that the compiler creates more than one function | 2366 // It is possible that the compiler creates more than one function |
2469 // object for the same closure, e.g. when inlining nodes from | 2367 // object for the same closure, e.g. when inlining nodes from |
2470 // finally clauses. If we already have a function object for the | 2368 // finally clauses. If we already have a function object for the |
2471 // same closure, do not add a second one. We compare token position, | 2369 // same closure, do not add a second one. We compare token position, |
2472 // and parent function to detect duplicates. | 2370 // and parent function to detect duplicates. |
2473 const Function& parent = Function::Handle(function.parent_function()); | 2371 const Function& parent = Function::Handle(function.parent_function()); |
2474 const Function& found_func = Function::Handle(Z, | 2372 const Function& found_func = Function::Handle( |
2475 isolate()->LookupClosureFunction(parent, function.token_pos())); | 2373 Z, isolate()->LookupClosureFunction(parent, function.token_pos())); |
2476 if (found_func.IsNull()) { | 2374 if (found_func.IsNull()) { |
2477 isolate()->AddClosureFunction(function); | 2375 isolate()->AddClosureFunction(function); |
2478 } | 2376 } |
2479 } | 2377 } |
2480 ASSERT(function.context_scope() != ContextScope::null()); | 2378 ASSERT(function.context_scope() != ContextScope::null()); |
2481 | 2379 |
2482 // The function type of a closure may have type arguments. In that case, | 2380 // The function type of a closure may have type arguments. In that case, |
2483 // pass the type arguments of the instantiator. | 2381 // pass the type arguments of the instantiator. |
2484 const Class& closure_class = | 2382 const Class& closure_class = |
2485 Class::ZoneHandle(Z, isolate()->object_store()->closure_class()); | 2383 Class::ZoneHandle(Z, isolate()->object_store()->closure_class()); |
2486 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = | 2384 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = |
2487 new(Z) ZoneGrowableArray<PushArgumentInstr*>(0); | 2385 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); |
2488 AllocateObjectInstr* alloc = new(Z) AllocateObjectInstr(node->token_pos(), | 2386 AllocateObjectInstr* alloc = new (Z) |
2489 closure_class, | 2387 AllocateObjectInstr(node->token_pos(), closure_class, no_arguments); |
2490 no_arguments); | |
2491 alloc->set_closure_function(function); | 2388 alloc->set_closure_function(function); |
2492 | 2389 |
2493 Value* closure_val = Bind(alloc); | 2390 Value* closure_val = Bind(alloc); |
2494 { LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val); | 2391 { |
| 2392 LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val); |
2495 // Store type arguments if scope class is generic. | 2393 // Store type arguments if scope class is generic. |
2496 const Type& function_type = Type::ZoneHandle(Z, function.SignatureType()); | 2394 const Type& function_type = Type::ZoneHandle(Z, function.SignatureType()); |
2497 const Class& scope_cls = Class::ZoneHandle(Z, function_type.type_class()); | 2395 const Class& scope_cls = Class::ZoneHandle(Z, function_type.type_class()); |
2498 if (scope_cls.IsGeneric()) { | 2396 if (scope_cls.IsGeneric()) { |
2499 ASSERT(function.Owner() == scope_cls.raw()); | 2397 ASSERT(function.Owner() == scope_cls.raw()); |
2500 Value* closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var, | 2398 Value* closure_tmp_val = |
2501 node->token_pos())); | 2399 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
2502 const Class& instantiator_class = Class::Handle( | 2400 const Class& instantiator_class = |
2503 Z, owner()->function().Owner()); | 2401 Class::Handle(Z, owner()->function().Owner()); |
2504 Value* type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), | 2402 Value* type_arguments = BuildInstantiatorTypeArguments( |
2505 instantiator_class, | 2403 node->token_pos(), instantiator_class, NULL); |
2506 NULL); | 2404 Do(new (Z) StoreInstanceFieldInstr(Closure::type_arguments_offset(), |
2507 Do(new(Z) StoreInstanceFieldInstr(Closure::type_arguments_offset(), | 2405 closure_tmp_val, type_arguments, |
2508 closure_tmp_val, | 2406 kEmitStoreBarrier, node->token_pos())); |
2509 type_arguments, | |
2510 kEmitStoreBarrier, | |
2511 node->token_pos())); | |
2512 } | 2407 } |
2513 | 2408 |
2514 // Store function. | 2409 // Store function. |
2515 Value* closure_tmp_val = | 2410 Value* closure_tmp_val = |
2516 Bind(new(Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); | 2411 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
2517 Value* func_val = | 2412 Value* func_val = |
2518 Bind(new(Z) ConstantInstr(Function::ZoneHandle(Z, function.raw()))); | 2413 Bind(new (Z) ConstantInstr(Function::ZoneHandle(Z, function.raw()))); |
2519 Do(new(Z) StoreInstanceFieldInstr(Closure::function_offset(), | 2414 Do(new (Z) StoreInstanceFieldInstr(Closure::function_offset(), |
2520 closure_tmp_val, | 2415 closure_tmp_val, func_val, |
2521 func_val, | 2416 kEmitStoreBarrier, node->token_pos())); |
2522 kEmitStoreBarrier, | |
2523 node->token_pos())); | |
2524 if (is_implicit) { | 2417 if (is_implicit) { |
2525 // Create new context containing the receiver. | 2418 // Create new context containing the receiver. |
2526 const intptr_t kNumContextVariables = 1; // The receiver. | 2419 const intptr_t kNumContextVariables = 1; // The receiver. |
2527 Value* allocated_context = | 2420 Value* allocated_context = Bind(new (Z) AllocateContextInstr( |
2528 Bind(new(Z) AllocateContextInstr(node->token_pos(), | 2421 node->token_pos(), kNumContextVariables)); |
2529 kNumContextVariables)); | 2422 { |
2530 { LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context); | 2423 LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context); |
2531 // Store receiver in context. | 2424 // Store receiver in context. |
2532 Value* context_tmp_val = | 2425 Value* context_tmp_val = |
2533 Bind(new(Z) LoadLocalInstr(*context_tmp_var, node->token_pos())); | 2426 Bind(new (Z) LoadLocalInstr(*context_tmp_var, node->token_pos())); |
2534 ValueGraphVisitor for_receiver(owner()); | 2427 ValueGraphVisitor for_receiver(owner()); |
2535 node->receiver()->Visit(&for_receiver); | 2428 node->receiver()->Visit(&for_receiver); |
2536 Append(for_receiver); | 2429 Append(for_receiver); |
2537 Value* receiver = for_receiver.value(); | 2430 Value* receiver = for_receiver.value(); |
2538 Do(new(Z) StoreInstanceFieldInstr(Context::variable_offset(0), | 2431 Do(new (Z) StoreInstanceFieldInstr( |
2539 context_tmp_val, | 2432 Context::variable_offset(0), context_tmp_val, receiver, |
2540 receiver, | 2433 kEmitStoreBarrier, node->token_pos())); |
2541 kEmitStoreBarrier, | |
2542 node->token_pos())); | |
2543 // Store new context in closure. | 2434 // Store new context in closure. |
2544 closure_tmp_val = | 2435 closure_tmp_val = |
2545 Bind(new(Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); | 2436 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
2546 context_tmp_val = | 2437 context_tmp_val = |
2547 Bind(new(Z) LoadLocalInstr(*context_tmp_var, node->token_pos())); | 2438 Bind(new (Z) LoadLocalInstr(*context_tmp_var, node->token_pos())); |
2548 Do(new(Z) StoreInstanceFieldInstr(Closure::context_offset(), | 2439 Do(new (Z) StoreInstanceFieldInstr( |
2549 closure_tmp_val, | 2440 Closure::context_offset(), closure_tmp_val, context_tmp_val, |
2550 context_tmp_val, | 2441 kEmitStoreBarrier, node->token_pos())); |
2551 kEmitStoreBarrier, | |
2552 node->token_pos())); | |
2553 Do(ExitTempLocalScope(allocated_context)); | 2442 Do(ExitTempLocalScope(allocated_context)); |
2554 } | 2443 } |
2555 } else { | 2444 } else { |
2556 // Store current context in closure. | 2445 // Store current context in closure. |
2557 closure_tmp_val = Bind( | 2446 closure_tmp_val = |
2558 new(Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); | 2447 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
2559 Value* context = Bind(BuildCurrentContext(node->token_pos())); | 2448 Value* context = Bind(BuildCurrentContext(node->token_pos())); |
2560 Do(new(Z) StoreInstanceFieldInstr(Closure::context_offset(), | 2449 Do(new (Z) StoreInstanceFieldInstr(Closure::context_offset(), |
2561 closure_tmp_val, | 2450 closure_tmp_val, context, |
2562 context, | 2451 kEmitStoreBarrier, node->token_pos())); |
2563 kEmitStoreBarrier, | |
2564 node->token_pos())); | |
2565 } | 2452 } |
2566 ReturnDefinition(ExitTempLocalScope(closure_val)); | 2453 ReturnDefinition(ExitTempLocalScope(closure_val)); |
2567 } | 2454 } |
2568 } | 2455 } |
2569 | 2456 |
2570 | 2457 |
2571 void EffectGraphVisitor::BuildPushArguments( | 2458 void EffectGraphVisitor::BuildPushArguments( |
2572 const ArgumentListNode& node, | 2459 const ArgumentListNode& node, |
2573 ZoneGrowableArray<PushArgumentInstr*>* values) { | 2460 ZoneGrowableArray<PushArgumentInstr*>* values) { |
2574 for (intptr_t i = 0; i < node.length(); ++i) { | 2461 for (intptr_t i = 0; i < node.length(); ++i) { |
2575 ValueGraphVisitor for_argument(owner()); | 2462 ValueGraphVisitor for_argument(owner()); |
2576 node.NodeAt(i)->Visit(&for_argument); | 2463 node.NodeAt(i)->Visit(&for_argument); |
2577 Append(for_argument); | 2464 Append(for_argument); |
2578 PushArgumentInstr* push_arg = PushArgument(for_argument.value()); | 2465 PushArgumentInstr* push_arg = PushArgument(for_argument.value()); |
2579 values->Add(push_arg); | 2466 values->Add(push_arg); |
2580 } | 2467 } |
2581 } | 2468 } |
2582 | 2469 |
2583 | 2470 |
2584 void EffectGraphVisitor::BuildInstanceCallConditional(InstanceCallNode* node) { | 2471 void EffectGraphVisitor::BuildInstanceCallConditional(InstanceCallNode* node) { |
2585 const TokenPosition token_pos = node->token_pos(); | 2472 const TokenPosition token_pos = node->token_pos(); |
2586 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); | 2473 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); |
2587 LoadLocalNode* load_temp = new(Z) LoadLocalNode(token_pos, temp_var); | 2474 LoadLocalNode* load_temp = new (Z) LoadLocalNode(token_pos, temp_var); |
2588 | 2475 |
2589 LiteralNode* null_constant = | 2476 LiteralNode* null_constant = |
2590 new(Z) LiteralNode(ST(token_pos), Object::null_instance()); | 2477 new (Z) LiteralNode(ST(token_pos), Object::null_instance()); |
2591 ComparisonNode* check_is_null = | 2478 ComparisonNode* check_is_null = new (Z) |
2592 new(Z) ComparisonNode(ST(token_pos), | 2479 ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant); |
2593 Token::kEQ, | |
2594 load_temp, | |
2595 null_constant); | |
2596 TestGraphVisitor for_test(owner(), ST(token_pos)); | 2480 TestGraphVisitor for_test(owner(), ST(token_pos)); |
2597 check_is_null->Visit(&for_test); | 2481 check_is_null->Visit(&for_test); |
2598 | 2482 |
2599 EffectGraphVisitor for_true(owner()); | 2483 EffectGraphVisitor for_true(owner()); |
2600 EffectGraphVisitor for_false(owner()); | 2484 EffectGraphVisitor for_false(owner()); |
2601 | 2485 |
2602 StoreLocalNode* store_null = | 2486 StoreLocalNode* store_null = |
2603 new(Z) StoreLocalNode(ST(token_pos), temp_var, null_constant); | 2487 new (Z) StoreLocalNode(ST(token_pos), temp_var, null_constant); |
2604 store_null->Visit(&for_true); | 2488 store_null->Visit(&for_true); |
2605 | 2489 |
2606 InstanceCallNode* call = | 2490 InstanceCallNode* call = new (Z) InstanceCallNode( |
2607 new(Z) InstanceCallNode(token_pos, | 2491 token_pos, load_temp, node->function_name(), node->arguments()); |
2608 load_temp, | |
2609 node->function_name(), | |
2610 node->arguments()); | |
2611 StoreLocalNode* store_result = | 2492 StoreLocalNode* store_result = |
2612 new(Z) StoreLocalNode(ST(token_pos), temp_var, call); | 2493 new (Z) StoreLocalNode(ST(token_pos), temp_var, call); |
2613 store_result->Visit(&for_false); | 2494 store_result->Visit(&for_false); |
2614 | 2495 |
2615 Join(for_test, for_true, for_false); | 2496 Join(for_test, for_true, for_false); |
2616 } | 2497 } |
2617 | 2498 |
2618 | 2499 |
2619 void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { | 2500 void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
2620 if (node->is_conditional()) { | 2501 if (node->is_conditional()) { |
2621 ValueGraphVisitor for_receiver(owner()); | 2502 ValueGraphVisitor for_receiver(owner()); |
2622 node->receiver()->Visit(&for_receiver); | 2503 node->receiver()->Visit(&for_receiver); |
2623 Append(for_receiver); | 2504 Append(for_receiver); |
2624 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); | 2505 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); |
2625 BuildInstanceCallConditional(node); | 2506 BuildInstanceCallConditional(node); |
2626 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); | 2507 ReturnDefinition(BuildLoadExprTemp(node->token_pos())); |
2627 } else { | 2508 } else { |
2628 EffectGraphVisitor::VisitInstanceCallNode(node); | 2509 EffectGraphVisitor::VisitInstanceCallNode(node); |
2629 } | 2510 } |
2630 } | 2511 } |
2631 | 2512 |
2632 | 2513 |
2633 void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { | 2514 void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) { |
2634 ValueGraphVisitor for_receiver(owner()); | 2515 ValueGraphVisitor for_receiver(owner()); |
2635 node->receiver()->Visit(&for_receiver); | 2516 node->receiver()->Visit(&for_receiver); |
2636 Append(for_receiver); | 2517 Append(for_receiver); |
2637 if (node->is_conditional()) { | 2518 if (node->is_conditional()) { |
2638 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); | 2519 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); |
2639 BuildInstanceCallConditional(node); | 2520 BuildInstanceCallConditional(node); |
2640 } else { | 2521 } else { |
2641 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 2522 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
2642 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2523 ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z) |
2643 new(Z) ZoneGrowableArray<PushArgumentInstr*>( | 2524 ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length() + 1); |
2644 node->arguments()->length() + 1); | |
2645 arguments->Add(push_receiver); | 2525 arguments->Add(push_receiver); |
2646 | 2526 |
2647 BuildPushArguments(*node->arguments(), arguments); | 2527 BuildPushArguments(*node->arguments(), arguments); |
2648 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 2528 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
2649 node->token_pos(), | 2529 node->token_pos(), node->function_name(), Token::kILLEGAL, arguments, |
2650 node->function_name(), | 2530 node->arguments()->names(), 1, owner()->ic_data_array()); |
2651 Token::kILLEGAL, | |
2652 arguments, | |
2653 node->arguments()->names(), | |
2654 1, | |
2655 owner()->ic_data_array()); | |
2656 ReturnDefinition(call); | 2531 ReturnDefinition(call); |
2657 } | 2532 } |
2658 } | 2533 } |
2659 | 2534 |
2660 | 2535 |
2661 // <Expression> ::= StaticCall { function: Function | 2536 // <Expression> ::= StaticCall { function: Function |
2662 // arguments: <ArgumentList> } | 2537 // arguments: <ArgumentList> } |
2663 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { | 2538 void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) { |
2664 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2539 ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z) |
2665 new(Z) ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); | 2540 ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); |
2666 BuildPushArguments(*node->arguments(), arguments); | 2541 BuildPushArguments(*node->arguments(), arguments); |
2667 StaticCallInstr* call = | 2542 StaticCallInstr* call = new (Z) StaticCallInstr( |
2668 new(Z) StaticCallInstr(node->token_pos(), | 2543 node->token_pos(), node->function(), node->arguments()->names(), |
2669 node->function(), | 2544 arguments, owner()->ic_data_array()); |
2670 node->arguments()->names(), | |
2671 arguments, | |
2672 owner()->ic_data_array()); | |
2673 if (node->function().recognized_kind() != MethodRecognizer::kUnknown) { | 2545 if (node->function().recognized_kind() != MethodRecognizer::kUnknown) { |
2674 call->set_result_cid(MethodRecognizer::ResultCid(node->function())); | 2546 call->set_result_cid(MethodRecognizer::ResultCid(node->function())); |
2675 } | 2547 } |
2676 ReturnDefinition(call); | 2548 ReturnDefinition(call); |
2677 } | 2549 } |
2678 | 2550 |
2679 | 2551 |
2680 void EffectGraphVisitor::BuildClosureCall( | 2552 void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node, |
2681 ClosureCallNode* node, bool result_needed) { | 2553 bool result_needed) { |
2682 ValueGraphVisitor for_closure(owner()); | 2554 ValueGraphVisitor for_closure(owner()); |
2683 node->closure()->Visit(&for_closure); | 2555 node->closure()->Visit(&for_closure); |
2684 Append(for_closure); | 2556 Append(for_closure); |
2685 | 2557 |
2686 Value* closure_value = for_closure.value(); | 2558 Value* closure_value = for_closure.value(); |
2687 LocalVariable* tmp_var = EnterTempLocalScope(closure_value); | 2559 LocalVariable* tmp_var = EnterTempLocalScope(closure_value); |
2688 | 2560 |
2689 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2561 ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z) |
2690 new(Z) ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); | 2562 ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length()); |
2691 Value* closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2563 Value* closure_val = |
| 2564 Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
2692 PushArgumentInstr* push_closure = PushArgument(closure_val); | 2565 PushArgumentInstr* push_closure = PushArgument(closure_val); |
2693 arguments->Add(push_closure); | 2566 arguments->Add(push_closure); |
2694 BuildPushArguments(*node->arguments(), arguments); | 2567 BuildPushArguments(*node->arguments(), arguments); |
2695 | 2568 |
2696 closure_val = Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2569 closure_val = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
2697 LoadFieldInstr* function_load = new(Z) LoadFieldInstr( | 2570 LoadFieldInstr* function_load = new (Z) LoadFieldInstr( |
2698 closure_val, | 2571 closure_val, Closure::function_offset(), |
2699 Closure::function_offset(), | 2572 AbstractType::ZoneHandle(Z, AbstractType::null()), node->token_pos()); |
2700 AbstractType::ZoneHandle(Z, AbstractType::null()), | |
2701 node->token_pos()); | |
2702 function_load->set_is_immutable(true); | 2573 function_load->set_is_immutable(true); |
2703 Value* function_val = Bind(function_load); | 2574 Value* function_val = Bind(function_load); |
2704 | 2575 |
2705 Definition* closure_call = | 2576 Definition* closure_call = |
2706 new(Z) ClosureCallInstr(function_val, node, arguments); | 2577 new (Z) ClosureCallInstr(function_val, node, arguments); |
2707 if (result_needed) { | 2578 if (result_needed) { |
2708 Value* result = Bind(closure_call); | 2579 Value* result = Bind(closure_call); |
2709 Do(new(Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos()))); | 2580 Do(new (Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos()))); |
2710 } else { | 2581 } else { |
2711 Do(closure_call); | 2582 Do(closure_call); |
2712 } | 2583 } |
2713 ReturnDefinition(ExitTempLocalScope(closure_value)); | 2584 ReturnDefinition(ExitTempLocalScope(closure_value)); |
2714 } | 2585 } |
2715 | 2586 |
2716 | 2587 |
2717 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2588 void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
2718 BuildClosureCall(node, false); | 2589 BuildClosureCall(node, false); |
2719 } | 2590 } |
2720 | 2591 |
2721 | 2592 |
2722 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { | 2593 void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) { |
2723 BuildClosureCall(node, true); | 2594 BuildClosureCall(node, true); |
2724 } | 2595 } |
2725 | 2596 |
2726 | 2597 |
2727 void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) { | 2598 void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) { |
2728 Value* field = Bind(new(Z) ConstantInstr( | 2599 Value* field = Bind( |
2729 Field::ZoneHandle(Z, node->field().Original()))); | 2600 new (Z) ConstantInstr(Field::ZoneHandle(Z, node->field().Original()))); |
2730 AddInstruction(new(Z) InitStaticFieldInstr(field, node->field())); | 2601 AddInstruction(new (Z) InitStaticFieldInstr(field, node->field())); |
2731 } | 2602 } |
2732 | 2603 |
2733 | 2604 |
2734 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { | 2605 void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) { |
2735 Value* context = Bind(BuildCurrentContext(node->token_pos())); | 2606 Value* context = Bind(BuildCurrentContext(node->token_pos())); |
2736 Value* clone = Bind(new(Z) CloneContextInstr(node->token_pos(), context)); | 2607 Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context)); |
2737 Do(BuildStoreContext(clone, node->token_pos())); | 2608 Do(BuildStoreContext(clone, node->token_pos())); |
2738 } | 2609 } |
2739 | 2610 |
2740 | 2611 |
2741 Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) { | 2612 Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) { |
2742 const Class& cls = Class::ZoneHandle(Z, node->constructor().Owner()); | 2613 const Class& cls = Class::ZoneHandle(Z, node->constructor().Owner()); |
2743 const bool cls_is_parameterized = cls.NumTypeArguments() > 0; | 2614 const bool cls_is_parameterized = cls.NumTypeArguments() > 0; |
2744 | 2615 |
2745 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = | 2616 ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = new (Z) |
2746 new(Z) ZoneGrowableArray<PushArgumentInstr*>( | 2617 ZoneGrowableArray<PushArgumentInstr*>(cls_is_parameterized ? 1 : 0); |
2747 cls_is_parameterized ? 1 : 0); | |
2748 if (cls_is_parameterized) { | 2618 if (cls_is_parameterized) { |
2749 Value* type_args = BuildInstantiatedTypeArguments(node->token_pos(), | 2619 Value* type_args = BuildInstantiatedTypeArguments(node->token_pos(), |
2750 node->type_arguments()); | 2620 node->type_arguments()); |
2751 allocate_arguments->Add(PushArgument(type_args)); | 2621 allocate_arguments->Add(PushArgument(type_args)); |
2752 } | 2622 } |
2753 | 2623 |
2754 Definition* allocation = new(Z) AllocateObjectInstr( | 2624 Definition* allocation = new (Z) AllocateObjectInstr( |
2755 node->token_pos(), | 2625 node->token_pos(), Class::ZoneHandle(Z, node->constructor().Owner()), |
2756 Class::ZoneHandle(Z, node->constructor().Owner()), | |
2757 allocate_arguments); | 2626 allocate_arguments); |
2758 | 2627 |
2759 return Bind(allocation); | 2628 return Bind(allocation); |
2760 } | 2629 } |
2761 | 2630 |
2762 | 2631 |
2763 void EffectGraphVisitor::BuildConstructorCall( | 2632 void EffectGraphVisitor::BuildConstructorCall( |
2764 ConstructorCallNode* node, | 2633 ConstructorCallNode* node, |
2765 PushArgumentInstr* push_alloc_value) { | 2634 PushArgumentInstr* push_alloc_value) { |
2766 | |
2767 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2635 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
2768 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 2636 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
2769 arguments->Add(push_alloc_value); | 2637 arguments->Add(push_alloc_value); |
2770 | 2638 |
2771 BuildPushArguments(*node->arguments(), arguments); | 2639 BuildPushArguments(*node->arguments(), arguments); |
2772 Do(new(Z) StaticCallInstr(node->token_pos(), | 2640 Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(), |
2773 node->constructor(), | 2641 node->arguments()->names(), arguments, |
2774 node->arguments()->names(), | 2642 owner()->ic_data_array())); |
2775 arguments, | |
2776 owner()->ic_data_array())); | |
2777 } | 2643 } |
2778 | 2644 |
2779 | 2645 |
2780 static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) { | 2646 static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) { |
2781 const Function& function = node->constructor(); | 2647 const Function& function = node->constructor(); |
2782 const Class& function_class = Class::Handle(function.Owner()); | 2648 const Class& function_class = Class::Handle(function.Owner()); |
2783 | 2649 |
2784 if ((function_class.library() != Library::CoreLibrary()) && | 2650 if ((function_class.library() != Library::CoreLibrary()) && |
2785 (function_class.library() != Library::TypedDataLibrary())) { | 2651 (function_class.library() != Library::TypedDataLibrary())) { |
2786 return kDynamicCid; | 2652 return kDynamicCid; |
2787 } | 2653 } |
2788 | 2654 |
2789 if (node->constructor().IsFactory()) { | 2655 if (node->constructor().IsFactory()) { |
2790 if ((function_class.Name() == Symbols::List().raw()) && | 2656 if ((function_class.Name() == Symbols::List().raw()) && |
2791 (function.name() == Symbols::ListFactory().raw())) { | 2657 (function.name() == Symbols::ListFactory().raw())) { |
2792 // Special recognition of 'new List()' vs 'new List(n)'. | 2658 // Special recognition of 'new List()' vs 'new List(n)'. |
2793 if (node->arguments()->length() == 0) { | 2659 if (node->arguments()->length() == 0) { |
2794 return kGrowableObjectArrayCid; | 2660 return kGrowableObjectArrayCid; |
2795 } | 2661 } |
2796 return kArrayCid; | 2662 return kArrayCid; |
2797 } | 2663 } |
2798 return FactoryRecognizer::ResultCid(function); | 2664 return FactoryRecognizer::ResultCid(function); |
2799 } | 2665 } |
2800 return kDynamicCid; // Not a known list constructor. | 2666 return kDynamicCid; // Not a known list constructor. |
2801 } | 2667 } |
2802 | 2668 |
2803 | 2669 |
2804 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { | 2670 void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
2805 if (node->constructor().IsFactory()) { | 2671 if (node->constructor().IsFactory()) { |
2806 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2672 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
2807 new(Z) ZoneGrowableArray<PushArgumentInstr*>(); | 2673 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); |
2808 PushArgumentInstr* push_type_arguments = PushArgument( | 2674 PushArgumentInstr* push_type_arguments = |
2809 BuildInstantiatedTypeArguments(node->token_pos(), | 2675 PushArgument(BuildInstantiatedTypeArguments(node->token_pos(), |
2810 node->type_arguments())); | 2676 node->type_arguments())); |
2811 arguments->Add(push_type_arguments); | 2677 arguments->Add(push_type_arguments); |
2812 ASSERT(arguments->length() == 1); | 2678 ASSERT(arguments->length() == 1); |
2813 BuildPushArguments(*node->arguments(), arguments); | 2679 BuildPushArguments(*node->arguments(), arguments); |
2814 StaticCallInstr* call = | 2680 StaticCallInstr* call = new (Z) StaticCallInstr( |
2815 new(Z) StaticCallInstr(node->token_pos(), | 2681 node->token_pos(), node->constructor(), node->arguments()->names(), |
2816 node->constructor(), | 2682 arguments, owner()->ic_data_array()); |
2817 node->arguments()->names(), | |
2818 arguments, | |
2819 owner()->ic_data_array()); | |
2820 const intptr_t result_cid = GetResultCidOfListFactory(node); | 2683 const intptr_t result_cid = GetResultCidOfListFactory(node); |
2821 if (result_cid != kDynamicCid) { | 2684 if (result_cid != kDynamicCid) { |
2822 call->set_result_cid(result_cid); | 2685 call->set_result_cid(result_cid); |
2823 call->set_is_known_list_constructor(true); | 2686 call->set_is_known_list_constructor(true); |
2824 // Recognized fixed length array factory must have two arguments: | 2687 // Recognized fixed length array factory must have two arguments: |
2825 // (0) type-arguments, (1) length. | 2688 // (0) type-arguments, (1) length. |
2826 ASSERT(!LoadFieldInstr::IsFixedLengthArrayCid(result_cid) || | 2689 ASSERT(!LoadFieldInstr::IsFixedLengthArrayCid(result_cid) || |
2827 arguments->length() == 2); | 2690 arguments->length() == 2); |
2828 } else if (node->constructor().recognized_kind() != | 2691 } else if (node->constructor().recognized_kind() != |
2829 MethodRecognizer::kUnknown) { | 2692 MethodRecognizer::kUnknown) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2864 // is not NULL. | 2727 // is not NULL. |
2865 Value* EffectGraphVisitor::BuildInstantiatorTypeArguments( | 2728 Value* EffectGraphVisitor::BuildInstantiatorTypeArguments( |
2866 TokenPosition token_pos, | 2729 TokenPosition token_pos, |
2867 const Class& instantiator_class, | 2730 const Class& instantiator_class, |
2868 Value* instantiator) { | 2731 Value* instantiator) { |
2869 if (!instantiator_class.IsGeneric()) { | 2732 if (!instantiator_class.IsGeneric()) { |
2870 // The type arguments are compile time constants. | 2733 // The type arguments are compile time constants. |
2871 TypeArguments& type_arguments = | 2734 TypeArguments& type_arguments = |
2872 TypeArguments::ZoneHandle(Z, TypeArguments::null()); | 2735 TypeArguments::ZoneHandle(Z, TypeArguments::null()); |
2873 // Type is temporary. Only its type arguments are preserved. | 2736 // Type is temporary. Only its type arguments are preserved. |
2874 Type& type = Type::Handle( | 2737 Type& type = Type::Handle(Z, Type::New(instantiator_class, type_arguments, |
2875 Z, | 2738 token_pos, Heap::kNew)); |
2876 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); | 2739 type ^= ClassFinalizer::FinalizeType(instantiator_class, type, |
2877 type ^= ClassFinalizer::FinalizeType( | 2740 ClassFinalizer::kFinalize); |
2878 instantiator_class, type, ClassFinalizer::kFinalize); | |
2879 ASSERT(!type.IsMalformedOrMalbounded()); | 2741 ASSERT(!type.IsMalformedOrMalbounded()); |
2880 type_arguments = type.arguments(); | 2742 type_arguments = type.arguments(); |
2881 type_arguments = type_arguments.Canonicalize(); | 2743 type_arguments = type_arguments.Canonicalize(); |
2882 return Bind(new(Z) ConstantInstr(type_arguments)); | 2744 return Bind(new (Z) ConstantInstr(type_arguments)); |
2883 } | 2745 } |
2884 Function& outer_function = Function::Handle(Z, owner()->function().raw()); | 2746 Function& outer_function = Function::Handle(Z, owner()->function().raw()); |
2885 while (outer_function.IsLocalFunction()) { | 2747 while (outer_function.IsLocalFunction()) { |
2886 outer_function = outer_function.parent_function(); | 2748 outer_function = outer_function.parent_function(); |
2887 } | 2749 } |
2888 if (outer_function.IsFactory()) { | 2750 if (outer_function.IsFactory()) { |
2889 // No instantiator for factories. | 2751 // No instantiator for factories. |
2890 ASSERT(instantiator == NULL); | 2752 ASSERT(instantiator == NULL); |
2891 LocalVariable* instantiator_var = | 2753 LocalVariable* instantiator_var = owner()->parsed_function().instantiator(); |
2892 owner()->parsed_function().instantiator(); | |
2893 ASSERT(instantiator_var != NULL); | 2754 ASSERT(instantiator_var != NULL); |
2894 return Bind(BuildLoadLocal(*instantiator_var, token_pos)); | 2755 return Bind(BuildLoadLocal(*instantiator_var, token_pos)); |
2895 } | 2756 } |
2896 if (instantiator == NULL) { | 2757 if (instantiator == NULL) { |
2897 instantiator = BuildInstantiator(token_pos); | 2758 instantiator = BuildInstantiator(token_pos); |
2898 } | 2759 } |
2899 // The instantiator is the receiver of the caller, which is not a factory. | 2760 // The instantiator is the receiver of the caller, which is not a factory. |
2900 // The receiver cannot be null; extract its TypeArguments object. | 2761 // The receiver cannot be null; extract its TypeArguments object. |
2901 // Note that in the factory case, the instantiator is the first parameter | 2762 // Note that in the factory case, the instantiator is the first parameter |
2902 // of the factory, i.e. already a TypeArguments object. | 2763 // of the factory, i.e. already a TypeArguments object. |
2903 intptr_t type_arguments_field_offset = | 2764 intptr_t type_arguments_field_offset = |
2904 instantiator_class.type_arguments_field_offset(); | 2765 instantiator_class.type_arguments_field_offset(); |
2905 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); | 2766 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); |
2906 | 2767 |
2907 return Bind(new(Z) LoadFieldInstr( | 2768 return Bind(new (Z) LoadFieldInstr( |
2908 instantiator, | 2769 instantiator, type_arguments_field_offset, |
2909 type_arguments_field_offset, | |
2910 Type::ZoneHandle(Z, Type::null()), // Not an instance, no type. | 2770 Type::ZoneHandle(Z, Type::null()), // Not an instance, no type. |
2911 token_pos)); | 2771 token_pos)); |
2912 } | 2772 } |
2913 | 2773 |
2914 | 2774 |
2915 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( | 2775 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( |
2916 TokenPosition token_pos, | 2776 TokenPosition token_pos, |
2917 const TypeArguments& type_arguments) { | 2777 const TypeArguments& type_arguments) { |
2918 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 2778 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
2919 return Bind(new(Z) ConstantInstr(type_arguments)); | 2779 return Bind(new (Z) ConstantInstr(type_arguments)); |
2920 } | 2780 } |
2921 // The type arguments are uninstantiated. | 2781 // The type arguments are uninstantiated. |
2922 const Class& instantiator_class = Class::ZoneHandle( | 2782 const Class& instantiator_class = |
2923 Z, owner()->function().Owner()); | 2783 Class::ZoneHandle(Z, owner()->function().Owner()); |
2924 Value* instantiator_value = | 2784 Value* instantiator_value = |
2925 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 2785 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
2926 const bool use_instantiator_type_args = | 2786 const bool use_instantiator_type_args = |
2927 type_arguments.IsUninstantiatedIdentity() || | 2787 type_arguments.IsUninstantiatedIdentity() || |
2928 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); | 2788 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); |
2929 if (use_instantiator_type_args) { | 2789 if (use_instantiator_type_args) { |
2930 return instantiator_value; | 2790 return instantiator_value; |
2931 } else { | 2791 } else { |
2932 return Bind(new(Z) InstantiateTypeArgumentsInstr(token_pos, | 2792 return Bind(new (Z) InstantiateTypeArgumentsInstr( |
2933 type_arguments, | 2793 token_pos, type_arguments, instantiator_class, instantiator_value)); |
2934 instantiator_class, | |
2935 instantiator_value)); | |
2936 } | 2794 } |
2937 } | 2795 } |
2938 | 2796 |
2939 | 2797 |
2940 void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { | 2798 void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) { |
2941 if (node->constructor().IsFactory()) { | 2799 if (node->constructor().IsFactory()) { |
2942 EffectGraphVisitor::VisitConstructorCallNode(node); | 2800 EffectGraphVisitor::VisitConstructorCallNode(node); |
2943 return; | 2801 return; |
2944 } | 2802 } |
2945 | 2803 |
2946 // t_n contains the allocated and initialized object. | 2804 // t_n contains the allocated and initialized object. |
2947 // t_n <- AllocateObject(class) | 2805 // t_n <- AllocateObject(class) |
2948 // t_n <- StoreLocal(temp, t_n); | 2806 // t_n <- StoreLocal(temp, t_n); |
2949 // t_n+1 <- ctor-arg | 2807 // t_n+1 <- ctor-arg |
2950 // t_n+2... <- constructor arguments start here | 2808 // t_n+2... <- constructor arguments start here |
2951 // StaticCall(constructor, t_n, t_n+1, ...) | 2809 // StaticCall(constructor, t_n, t_n+1, ...) |
2952 // tn <- LoadLocal(temp) | 2810 // tn <- LoadLocal(temp) |
2953 | 2811 |
2954 Value* allocate = BuildObjectAllocation(node); | 2812 Value* allocate = BuildObjectAllocation(node); |
2955 { LocalVariable* tmp_var = EnterTempLocalScope(allocate); | 2813 { |
| 2814 LocalVariable* tmp_var = EnterTempLocalScope(allocate); |
2956 Value* allocated_tmp = | 2815 Value* allocated_tmp = |
2957 Bind(new(Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 2816 Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
2958 PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp); | 2817 PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp); |
2959 BuildConstructorCall(node, push_allocated_value); | 2818 BuildConstructorCall(node, push_allocated_value); |
2960 ReturnDefinition(ExitTempLocalScope(allocate)); | 2819 ReturnDefinition(ExitTempLocalScope(allocate)); |
2961 } | 2820 } |
2962 } | 2821 } |
2963 | 2822 |
2964 | 2823 |
2965 | |
2966 void EffectGraphVisitor::BuildInstanceGetterConditional( | 2824 void EffectGraphVisitor::BuildInstanceGetterConditional( |
2967 InstanceGetterNode* node) { | 2825 InstanceGetterNode* node) { |
2968 const TokenPosition token_pos = node->token_pos(); | 2826 const TokenPosition token_pos = node->token_pos(); |
2969 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); | 2827 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); |
2970 LoadLocalNode* load_temp = new(Z) LoadLocalNode(token_pos, temp_var); | 2828 LoadLocalNode* load_temp = new (Z) LoadLocalNode(token_pos, temp_var); |
2971 | 2829 |
2972 LiteralNode* null_constant = | 2830 LiteralNode* null_constant = |
2973 new(Z) LiteralNode(ST(token_pos), Object::null_instance()); | 2831 new (Z) LiteralNode(ST(token_pos), Object::null_instance()); |
2974 ComparisonNode* check_is_null = | 2832 ComparisonNode* check_is_null = new (Z) |
2975 new(Z) ComparisonNode(ST(token_pos), | 2833 ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant); |
2976 Token::kEQ, | |
2977 load_temp, | |
2978 null_constant); | |
2979 TestGraphVisitor for_test(owner(), ST(token_pos)); | 2834 TestGraphVisitor for_test(owner(), ST(token_pos)); |
2980 check_is_null->Visit(&for_test); | 2835 check_is_null->Visit(&for_test); |
2981 | 2836 |
2982 EffectGraphVisitor for_true(owner()); | 2837 EffectGraphVisitor for_true(owner()); |
2983 EffectGraphVisitor for_false(owner()); | 2838 EffectGraphVisitor for_false(owner()); |
2984 | 2839 |
2985 StoreLocalNode* store_null = | 2840 StoreLocalNode* store_null = |
2986 new(Z) StoreLocalNode(ST(token_pos), temp_var, null_constant); | 2841 new (Z) StoreLocalNode(ST(token_pos), temp_var, null_constant); |
2987 store_null->Visit(&for_true); | 2842 store_null->Visit(&for_true); |
2988 | 2843 |
2989 InstanceGetterNode* getter = new(Z) InstanceGetterNode(token_pos, | 2844 InstanceGetterNode* getter = |
2990 load_temp, | 2845 new (Z) InstanceGetterNode(token_pos, load_temp, node->field_name()); |
2991 node->field_name()); | |
2992 StoreLocalNode* store_getter = | 2846 StoreLocalNode* store_getter = |
2993 new(Z) StoreLocalNode(ST(token_pos), temp_var, getter); | 2847 new (Z) StoreLocalNode(ST(token_pos), temp_var, getter); |
2994 store_getter->Visit(&for_false); | 2848 store_getter->Visit(&for_false); |
2995 | 2849 |
2996 Join(for_test, for_true, for_false); | 2850 Join(for_test, for_true, for_false); |
2997 } | 2851 } |
2998 | 2852 |
2999 | 2853 |
3000 void ValueGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { | 2854 void ValueGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
3001 if (node->is_conditional()) { | 2855 if (node->is_conditional()) { |
3002 ValueGraphVisitor for_receiver(owner()); | 2856 ValueGraphVisitor for_receiver(owner()); |
3003 node->receiver()->Visit(&for_receiver); | 2857 node->receiver()->Visit(&for_receiver); |
(...skipping 10 matching lines...) Expand all Loading... |
3014 void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { | 2868 void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) { |
3015 ValueGraphVisitor for_receiver(owner()); | 2869 ValueGraphVisitor for_receiver(owner()); |
3016 node->receiver()->Visit(&for_receiver); | 2870 node->receiver()->Visit(&for_receiver); |
3017 Append(for_receiver); | 2871 Append(for_receiver); |
3018 if (node->is_conditional()) { | 2872 if (node->is_conditional()) { |
3019 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); | 2873 Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos())); |
3020 BuildInstanceGetterConditional(node); | 2874 BuildInstanceGetterConditional(node); |
3021 } else { | 2875 } else { |
3022 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); | 2876 PushArgumentInstr* push_receiver = PushArgument(for_receiver.value()); |
3023 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2877 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3024 new(Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 2878 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
3025 arguments->Add(push_receiver); | 2879 arguments->Add(push_receiver); |
3026 const String& name = | 2880 const String& name = |
3027 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); | 2881 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); |
3028 InstanceCallInstr* call = new(Z) InstanceCallInstr( | 2882 InstanceCallInstr* call = new (Z) |
3029 node->token_pos(), | 2883 InstanceCallInstr(node->token_pos(), name, Token::kGET, arguments, |
3030 name, | 2884 Object::null_array(), 1, owner()->ic_data_array()); |
3031 Token::kGET, | |
3032 arguments, Object::null_array(), | |
3033 1, | |
3034 owner()->ic_data_array()); | |
3035 ReturnDefinition(call); | 2885 ReturnDefinition(call); |
3036 } | 2886 } |
3037 } | 2887 } |
3038 | 2888 |
3039 | 2889 |
3040 void EffectGraphVisitor::BuildInstanceSetterArguments( | 2890 void EffectGraphVisitor::BuildInstanceSetterArguments( |
3041 InstanceSetterNode* node, | 2891 InstanceSetterNode* node, |
3042 ZoneGrowableArray<PushArgumentInstr*>* arguments, | 2892 ZoneGrowableArray<PushArgumentInstr*>* arguments, |
3043 bool result_is_needed) { | 2893 bool result_is_needed) { |
3044 ValueGraphVisitor for_receiver(owner()); | 2894 ValueGraphVisitor for_receiver(owner()); |
(...skipping 17 matching lines...) Expand all Loading... |
3062 | 2912 |
3063 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { | 2913 void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
3064 const TokenPosition token_pos = node->token_pos(); | 2914 const TokenPosition token_pos = node->token_pos(); |
3065 if (node->is_conditional()) { | 2915 if (node->is_conditional()) { |
3066 ValueGraphVisitor for_receiver(owner()); | 2916 ValueGraphVisitor for_receiver(owner()); |
3067 node->receiver()->Visit(&for_receiver); | 2917 node->receiver()->Visit(&for_receiver); |
3068 Append(for_receiver); | 2918 Append(for_receiver); |
3069 Do(BuildStoreExprTemp(for_receiver.value(), token_pos)); | 2919 Do(BuildStoreExprTemp(for_receiver.value(), token_pos)); |
3070 | 2920 |
3071 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); | 2921 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); |
3072 LoadLocalNode* load_temp = | 2922 LoadLocalNode* load_temp = new (Z) LoadLocalNode(ST(token_pos), temp_var); |
3073 new(Z) LoadLocalNode(ST(token_pos), temp_var); | |
3074 LiteralNode* null_constant = | 2923 LiteralNode* null_constant = |
3075 new(Z) LiteralNode(ST(token_pos), Object::null_instance()); | 2924 new (Z) LiteralNode(ST(token_pos), Object::null_instance()); |
3076 ComparisonNode* check_is_null = | 2925 ComparisonNode* check_is_null = new (Z) |
3077 new(Z) ComparisonNode(ST(token_pos), | 2926 ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant); |
3078 Token::kEQ, | |
3079 load_temp, | |
3080 null_constant); | |
3081 TestGraphVisitor for_test(owner(), ST(token_pos)); | 2927 TestGraphVisitor for_test(owner(), ST(token_pos)); |
3082 check_is_null->Visit(&for_test); | 2928 check_is_null->Visit(&for_test); |
3083 | 2929 |
3084 EffectGraphVisitor for_true(owner()); | 2930 EffectGraphVisitor for_true(owner()); |
3085 EffectGraphVisitor for_false(owner()); | 2931 EffectGraphVisitor for_false(owner()); |
3086 | 2932 |
3087 InstanceSetterNode* setter = | 2933 InstanceSetterNode* setter = new (Z) InstanceSetterNode( |
3088 new(Z) InstanceSetterNode(token_pos, | 2934 token_pos, load_temp, node->field_name(), node->value()); |
3089 load_temp, | |
3090 node->field_name(), | |
3091 node->value()); | |
3092 setter->Visit(&for_false); | 2935 setter->Visit(&for_false); |
3093 Join(for_test, for_true, for_false); | 2936 Join(for_test, for_true, for_false); |
3094 return; | 2937 return; |
3095 } | 2938 } |
3096 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2939 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3097 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 2940 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
3098 BuildInstanceSetterArguments(node, arguments, kResultNotNeeded); | 2941 BuildInstanceSetterArguments(node, arguments, kResultNotNeeded); |
3099 const String& name = | 2942 const String& name = |
3100 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 2943 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
3101 const intptr_t kNumArgsChecked = 1; // Do not check value type. | 2944 const intptr_t kNumArgsChecked = 1; // Do not check value type. |
3102 InstanceCallInstr* call = new(Z) InstanceCallInstr(token_pos, | 2945 InstanceCallInstr* call = new (Z) InstanceCallInstr( |
3103 name, | 2946 token_pos, name, Token::kSET, arguments, Object::null_array(), |
3104 Token::kSET, | 2947 kNumArgsChecked, owner()->ic_data_array()); |
3105 arguments, | |
3106 Object::null_array(), | |
3107 kNumArgsChecked, | |
3108 owner()->ic_data_array()); | |
3109 ReturnDefinition(call); | 2948 ReturnDefinition(call); |
3110 } | 2949 } |
3111 | 2950 |
3112 | 2951 |
3113 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { | 2952 void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) { |
3114 const TokenPosition token_pos = node->token_pos(); | 2953 const TokenPosition token_pos = node->token_pos(); |
3115 if (node->is_conditional()) { | 2954 if (node->is_conditional()) { |
3116 ValueGraphVisitor for_receiver(owner()); | 2955 ValueGraphVisitor for_receiver(owner()); |
3117 node->receiver()->Visit(&for_receiver); | 2956 node->receiver()->Visit(&for_receiver); |
3118 Append(for_receiver); | 2957 Append(for_receiver); |
3119 Do(BuildStoreExprTemp(for_receiver.value(), token_pos)); | 2958 Do(BuildStoreExprTemp(for_receiver.value(), token_pos)); |
3120 | 2959 |
3121 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); | 2960 LocalVariable* temp_var = owner()->parsed_function().expression_temp_var(); |
3122 LoadLocalNode* load_temp = | 2961 LoadLocalNode* load_temp = new (Z) LoadLocalNode(ST(token_pos), temp_var); |
3123 new(Z) LoadLocalNode(ST(token_pos), temp_var); | |
3124 LiteralNode* null_constant = | 2962 LiteralNode* null_constant = |
3125 new(Z) LiteralNode(ST(token_pos), Object::null_instance()); | 2963 new (Z) LiteralNode(ST(token_pos), Object::null_instance()); |
3126 ComparisonNode* check_is_null = | 2964 ComparisonNode* check_is_null = new (Z) |
3127 new(Z) ComparisonNode(ST(token_pos), | 2965 ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant); |
3128 Token::kEQ, | |
3129 load_temp, | |
3130 null_constant); | |
3131 TestGraphVisitor for_test(owner(), ST(token_pos)); | 2966 TestGraphVisitor for_test(owner(), ST(token_pos)); |
3132 check_is_null->Visit(&for_test); | 2967 check_is_null->Visit(&for_test); |
3133 | 2968 |
3134 ValueGraphVisitor for_true(owner()); | 2969 ValueGraphVisitor for_true(owner()); |
3135 null_constant->Visit(&for_true); | 2970 null_constant->Visit(&for_true); |
3136 for_true.Do(BuildStoreExprTemp(for_true.value(), token_pos)); | 2971 for_true.Do(BuildStoreExprTemp(for_true.value(), token_pos)); |
3137 | 2972 |
3138 ValueGraphVisitor for_false(owner()); | 2973 ValueGraphVisitor for_false(owner()); |
3139 InstanceSetterNode* setter = | 2974 InstanceSetterNode* setter = new (Z) InstanceSetterNode( |
3140 new(Z) InstanceSetterNode(token_pos, | 2975 token_pos, load_temp, node->field_name(), node->value()); |
3141 load_temp, | |
3142 node->field_name(), | |
3143 node->value()); | |
3144 setter->Visit(&for_false); | 2976 setter->Visit(&for_false); |
3145 for_false.Do(BuildStoreExprTemp(for_false.value(), token_pos)); | 2977 for_false.Do(BuildStoreExprTemp(for_false.value(), token_pos)); |
3146 | 2978 |
3147 Join(for_test, for_true, for_false); | 2979 Join(for_test, for_true, for_false); |
3148 ReturnDefinition(BuildLoadExprTemp(token_pos)); | 2980 ReturnDefinition(BuildLoadExprTemp(token_pos)); |
3149 return; | 2981 return; |
3150 } | 2982 } |
3151 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2983 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3152 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 2984 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
3153 BuildInstanceSetterArguments(node, arguments, kResultNeeded); | 2985 BuildInstanceSetterArguments(node, arguments, kResultNeeded); |
3154 const String& name = | 2986 const String& name = |
3155 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 2987 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
3156 const intptr_t kNumArgsChecked = 1; // Do not check value type. | 2988 const intptr_t kNumArgsChecked = 1; // Do not check value type. |
3157 Do(new(Z) InstanceCallInstr(token_pos, | 2989 Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments, |
3158 name, | 2990 Object::null_array(), kNumArgsChecked, |
3159 Token::kSET, | 2991 owner()->ic_data_array())); |
3160 arguments, | |
3161 Object::null_array(), | |
3162 kNumArgsChecked, | |
3163 owner()->ic_data_array())); | |
3164 ReturnDefinition(BuildLoadExprTemp(token_pos)); | 2992 ReturnDefinition(BuildLoadExprTemp(token_pos)); |
3165 } | 2993 } |
3166 | 2994 |
3167 | 2995 |
3168 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { | 2996 void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) { |
3169 const String& getter_name = | 2997 const String& getter_name = |
3170 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); | 2998 String::ZoneHandle(Z, Field::GetterSymbol(node->field_name())); |
3171 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 2999 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3172 new(Z) ZoneGrowableArray<PushArgumentInstr*>(); | 3000 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); |
3173 Function& getter_function = Function::ZoneHandle(Z, Function::null()); | 3001 Function& getter_function = Function::ZoneHandle(Z, Function::null()); |
3174 if (node->is_super_getter()) { | 3002 if (node->is_super_getter()) { |
3175 // Statically resolved instance getter, i.e. "super getter". | 3003 // Statically resolved instance getter, i.e. "super getter". |
3176 ASSERT(node->receiver() != NULL); | 3004 ASSERT(node->receiver() != NULL); |
3177 getter_function = Resolver::ResolveDynamicAnyArgs(Z, | 3005 getter_function = |
3178 node->cls(), getter_name); | 3006 Resolver::ResolveDynamicAnyArgs(Z, node->cls(), getter_name); |
3179 if (getter_function.IsNull()) { | 3007 if (getter_function.IsNull()) { |
3180 // Resolve and call noSuchMethod. | 3008 // Resolve and call noSuchMethod. |
3181 ArgumentListNode* arguments = new(Z) ArgumentListNode(node->token_pos()); | 3009 ArgumentListNode* arguments = new (Z) ArgumentListNode(node->token_pos()); |
3182 arguments->Add(node->receiver()); | 3010 arguments->Add(node->receiver()); |
3183 StaticCallInstr* call = | 3011 StaticCallInstr* call = BuildStaticNoSuchMethodCall( |
3184 BuildStaticNoSuchMethodCall(node->cls(), | 3012 node->cls(), node->receiver(), getter_name, arguments, |
3185 node->receiver(), | 3013 false, // Don't save last argument. |
3186 getter_name, | 3014 true); // Super invocation. |
3187 arguments, | |
3188 false, // Don't save last argument. | |
3189 true); // Super invocation. | |
3190 ReturnDefinition(call); | 3015 ReturnDefinition(call); |
3191 return; | 3016 return; |
3192 } else { | 3017 } else { |
3193 ValueGraphVisitor receiver_value(owner()); | 3018 ValueGraphVisitor receiver_value(owner()); |
3194 node->receiver()->Visit(&receiver_value); | 3019 node->receiver()->Visit(&receiver_value); |
3195 Append(receiver_value); | 3020 Append(receiver_value); |
3196 arguments->Add(PushArgument(receiver_value.value())); | 3021 arguments->Add(PushArgument(receiver_value.value())); |
3197 } | 3022 } |
3198 } else { | 3023 } else { |
3199 getter_function = node->cls().LookupStaticFunction(getter_name); | 3024 getter_function = node->cls().LookupStaticFunction(getter_name); |
3200 if (getter_function.IsNull()) { | 3025 if (getter_function.IsNull()) { |
3201 // When the parser encounters a reference to a static field materialized | 3026 // When the parser encounters a reference to a static field materialized |
3202 // only by a static setter, but no corresponding static getter, it creates | 3027 // only by a static setter, but no corresponding static getter, it creates |
3203 // a StaticGetterNode ast node referring to the non-existing static getter | 3028 // a StaticGetterNode ast node referring to the non-existing static getter |
3204 // for the case this field reference appears in a left hand side | 3029 // for the case this field reference appears in a left hand side |
3205 // expression (the parser has not distinguished between left and right | 3030 // expression (the parser has not distinguished between left and right |
3206 // hand side yet at this stage). If the parser establishes later that the | 3031 // hand side yet at this stage). If the parser establishes later that the |
3207 // field access is part of a left hand side expression, the | 3032 // field access is part of a left hand side expression, the |
3208 // StaticGetterNode is transformed into a StaticSetterNode referring to | 3033 // StaticGetterNode is transformed into a StaticSetterNode referring to |
3209 // the existing static setter. | 3034 // the existing static setter. |
3210 // However, if the field reference appears in a right hand side | 3035 // However, if the field reference appears in a right hand side |
3211 // expression, no such transformation occurs and we land here with a | 3036 // expression, no such transformation occurs and we land here with a |
3212 // StaticGetterNode missing a getter function, so we throw a | 3037 // StaticGetterNode missing a getter function, so we throw a |
3213 // NoSuchMethodError. | 3038 // NoSuchMethodError. |
3214 | 3039 |
3215 // Throw a NoSuchMethodError. | 3040 // Throw a NoSuchMethodError. |
3216 StaticCallInstr* call = BuildThrowNoSuchMethodError( | 3041 StaticCallInstr* call = BuildThrowNoSuchMethodError( |
3217 node->token_pos(), | 3042 node->token_pos(), node->cls(), getter_name, |
3218 node->cls(), | |
3219 getter_name, | |
3220 NULL, // No Arguments to getter. | 3043 NULL, // No Arguments to getter. |
3221 InvocationMirror::EncodeType( | 3044 InvocationMirror::EncodeType(node->cls().IsTopLevel() |
3222 node->cls().IsTopLevel() ? | 3045 ? InvocationMirror::kTopLevel |
3223 InvocationMirror::kTopLevel : | 3046 : InvocationMirror::kStatic, |
3224 InvocationMirror::kStatic, | 3047 InvocationMirror::kGetter)); |
3225 InvocationMirror::kGetter)); | |
3226 ReturnDefinition(call); | 3048 ReturnDefinition(call); |
3227 return; | 3049 return; |
3228 } | 3050 } |
3229 } | 3051 } |
3230 ASSERT(!getter_function.IsNull()); | 3052 ASSERT(!getter_function.IsNull()); |
3231 StaticCallInstr* call = new(Z) StaticCallInstr( | 3053 StaticCallInstr* call = |
3232 node->token_pos(), | 3054 new (Z) StaticCallInstr(node->token_pos(), getter_function, |
3233 getter_function, | 3055 Object::null_array(), // No names |
3234 Object::null_array(), // No names | 3056 arguments, owner()->ic_data_array()); |
3235 arguments, | |
3236 owner()->ic_data_array()); | |
3237 ReturnDefinition(call); | 3057 ReturnDefinition(call); |
3238 } | 3058 } |
3239 | 3059 |
3240 | 3060 |
3241 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, | 3061 void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node, |
3242 bool result_is_needed) { | 3062 bool result_is_needed) { |
3243 const String& setter_name = | 3063 const String& setter_name = |
3244 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); | 3064 String::ZoneHandle(Z, Field::SetterSymbol(node->field_name())); |
3245 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3065 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3246 new(Z) ZoneGrowableArray<PushArgumentInstr*>(1); | 3066 new (Z) ZoneGrowableArray<PushArgumentInstr*>(1); |
3247 const TokenPosition token_pos = node->token_pos(); | 3067 const TokenPosition token_pos = node->token_pos(); |
3248 // A super setter is an instance setter whose setter function is | 3068 // A super setter is an instance setter whose setter function is |
3249 // resolved at compile time (in the caller instance getter's super class). | 3069 // resolved at compile time (in the caller instance getter's super class). |
3250 // Unlike a static getter, a super getter has a receiver parameter. | 3070 // Unlike a static getter, a super getter has a receiver parameter. |
3251 const bool is_super_setter = (node->receiver() != NULL); | 3071 const bool is_super_setter = (node->receiver() != NULL); |
3252 const Function& setter_function = node->function(); | 3072 const Function& setter_function = node->function(); |
3253 StaticCallInstr* call; | 3073 StaticCallInstr* call; |
3254 if (setter_function.IsNull()) { | 3074 if (setter_function.IsNull()) { |
3255 if (is_super_setter) { | 3075 if (is_super_setter) { |
3256 ASSERT(node->receiver() != NULL); | 3076 ASSERT(node->receiver() != NULL); |
3257 // Resolve and call noSuchMethod. | 3077 // Resolve and call noSuchMethod. |
3258 ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos); | 3078 ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos); |
3259 arguments->Add(node->receiver()); | 3079 arguments->Add(node->receiver()); |
3260 arguments->Add(node->value()); | 3080 arguments->Add(node->value()); |
3261 call = BuildStaticNoSuchMethodCall( | 3081 call = BuildStaticNoSuchMethodCall( |
3262 node->cls(), | 3082 node->cls(), node->receiver(), setter_name, arguments, |
3263 node->receiver(), | |
3264 setter_name, | |
3265 arguments, | |
3266 result_is_needed, // Save last arg if result is needed. | 3083 result_is_needed, // Save last arg if result is needed. |
3267 true); // Super invocation. | 3084 true); // Super invocation. |
3268 } else { | 3085 } else { |
3269 // Throw a NoSuchMethodError. | 3086 // Throw a NoSuchMethodError. |
3270 ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos); | 3087 ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos); |
3271 arguments->Add(node->value()); | 3088 arguments->Add(node->value()); |
3272 call = BuildThrowNoSuchMethodError( | 3089 call = BuildThrowNoSuchMethodError( |
3273 token_pos, | 3090 token_pos, node->cls(), setter_name, |
3274 node->cls(), | |
3275 setter_name, | |
3276 arguments, // Argument is the value passed to the setter. | 3091 arguments, // Argument is the value passed to the setter. |
3277 InvocationMirror::EncodeType( | 3092 InvocationMirror::EncodeType(node->cls().IsTopLevel() |
3278 node->cls().IsTopLevel() ? | 3093 ? InvocationMirror::kTopLevel |
3279 InvocationMirror::kTopLevel : | 3094 : InvocationMirror::kStatic, |
3280 InvocationMirror::kStatic, | 3095 InvocationMirror::kSetter)); |
3281 InvocationMirror::kSetter)); | |
3282 } | 3096 } |
3283 } else { | 3097 } else { |
3284 if (is_super_setter) { | 3098 if (is_super_setter) { |
3285 // Add receiver of instance getter. | 3099 // Add receiver of instance getter. |
3286 ValueGraphVisitor for_receiver(owner()); | 3100 ValueGraphVisitor for_receiver(owner()); |
3287 node->receiver()->Visit(&for_receiver); | 3101 node->receiver()->Visit(&for_receiver); |
3288 Append(for_receiver); | 3102 Append(for_receiver); |
3289 arguments->Add(PushArgument(for_receiver.value())); | 3103 arguments->Add(PushArgument(for_receiver.value())); |
3290 } | 3104 } |
3291 ValueGraphVisitor for_value(owner()); | 3105 ValueGraphVisitor for_value(owner()); |
3292 node->value()->Visit(&for_value); | 3106 node->value()->Visit(&for_value); |
3293 Append(for_value); | 3107 Append(for_value); |
3294 Value* value = NULL; | 3108 Value* value = NULL; |
3295 if (result_is_needed) { | 3109 if (result_is_needed) { |
3296 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); | 3110 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); |
3297 } else { | 3111 } else { |
3298 value = for_value.value(); | 3112 value = for_value.value(); |
3299 } | 3113 } |
3300 arguments->Add(PushArgument(value)); | 3114 arguments->Add(PushArgument(value)); |
3301 | 3115 |
3302 call = new(Z) StaticCallInstr(token_pos, | 3116 call = new (Z) StaticCallInstr(token_pos, setter_function, |
3303 setter_function, | 3117 Object::null_array(), // No names. |
3304 Object::null_array(), // No names. | 3118 arguments, owner()->ic_data_array()); |
3305 arguments, | |
3306 owner()->ic_data_array()); | |
3307 } | 3119 } |
3308 if (result_is_needed) { | 3120 if (result_is_needed) { |
3309 Do(call); | 3121 Do(call); |
3310 ReturnDefinition(BuildLoadExprTemp(token_pos)); | 3122 ReturnDefinition(BuildLoadExprTemp(token_pos)); |
3311 } else { | 3123 } else { |
3312 ReturnDefinition(call); | 3124 ReturnDefinition(call); |
3313 } | 3125 } |
3314 } | 3126 } |
3315 | 3127 |
3316 | 3128 |
(...skipping 19 matching lines...) Expand all Loading... |
3336 return TypedData::length_offset(); | 3148 return TypedData::length_offset(); |
3337 case MethodRecognizer::kGrowableArrayLength: | 3149 case MethodRecognizer::kGrowableArrayLength: |
3338 return GrowableObjectArray::length_offset(); | 3150 return GrowableObjectArray::length_offset(); |
3339 default: | 3151 default: |
3340 UNREACHABLE(); | 3152 UNREACHABLE(); |
3341 return 0; | 3153 return 0; |
3342 } | 3154 } |
3343 } | 3155 } |
3344 | 3156 |
3345 | 3157 |
3346 LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar( | 3158 LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(LocalScope* scope, |
3347 LocalScope* scope, TokenPosition token_pos) { | 3159 TokenPosition token_pos) { |
3348 LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(), | 3160 LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(), |
3349 true); // Test only. | 3161 true); // Test only. |
3350 return new(Z) LoadLocalInstr(*receiver_var, token_pos); | 3162 return new (Z) LoadLocalInstr(*receiver_var, token_pos); |
3351 } | 3163 } |
3352 | 3164 |
3353 | 3165 |
3354 LoadFieldInstr* EffectGraphVisitor::BuildNativeGetter( | 3166 LoadFieldInstr* EffectGraphVisitor::BuildNativeGetter( |
3355 NativeBodyNode* node, | 3167 NativeBodyNode* node, |
3356 MethodRecognizer::Kind kind, | 3168 MethodRecognizer::Kind kind, |
3357 intptr_t offset, | 3169 intptr_t offset, |
3358 const Type& type, | 3170 const Type& type, |
3359 intptr_t class_id) { | 3171 intptr_t class_id) { |
3360 Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos())); | 3172 Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos())); |
3361 LoadFieldInstr* load = new(Z) LoadFieldInstr(receiver, | 3173 LoadFieldInstr* load = |
3362 offset, | 3174 new (Z) LoadFieldInstr(receiver, offset, type, node->token_pos()); |
3363 type, | |
3364 node->token_pos()); | |
3365 load->set_result_cid(class_id); | 3175 load->set_result_cid(class_id); |
3366 load->set_recognized_kind(kind); | 3176 load->set_recognized_kind(kind); |
3367 return load; | 3177 return load; |
3368 } | 3178 } |
3369 | 3179 |
3370 | 3180 |
3371 ConstantInstr* EffectGraphVisitor::DoNativeSetterStoreValue( | 3181 ConstantInstr* EffectGraphVisitor::DoNativeSetterStoreValue( |
3372 NativeBodyNode* node, | 3182 NativeBodyNode* node, |
3373 intptr_t offset, | 3183 intptr_t offset, |
3374 StoreBarrierType emit_store_barrier) { | 3184 StoreBarrierType emit_store_barrier) { |
3375 Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos())); | 3185 Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos())); |
3376 LocalVariable* value_var = | 3186 LocalVariable* value_var = |
3377 node->scope()->LookupVariable(Symbols::Value(), true); | 3187 node->scope()->LookupVariable(Symbols::Value(), true); |
3378 Value* value = Bind(new(Z) LoadLocalInstr(*value_var, node->token_pos())); | 3188 Value* value = Bind(new (Z) LoadLocalInstr(*value_var, node->token_pos())); |
3379 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | 3189 StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr( |
3380 offset, | 3190 offset, receiver, value, emit_store_barrier, node->token_pos()); |
3381 receiver, | |
3382 value, | |
3383 emit_store_barrier, | |
3384 node->token_pos()); | |
3385 Do(store); | 3191 Do(store); |
3386 return new(Z) ConstantInstr(Object::ZoneHandle(Z, Object::null())); | 3192 return new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null())); |
3387 } | 3193 } |
3388 | 3194 |
3389 | 3195 |
3390 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { | 3196 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
3391 const Function& function = owner()->function(); | 3197 const Function& function = owner()->function(); |
3392 const TokenPosition token_pos = node->token_pos(); | 3198 const TokenPosition token_pos = node->token_pos(); |
3393 if (!function.IsClosureFunction()) { | 3199 if (!function.IsClosureFunction()) { |
3394 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 3200 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
3395 switch (kind) { | 3201 switch (kind) { |
3396 case MethodRecognizer::kObjectEquals: { | 3202 case MethodRecognizer::kObjectEquals: { |
3397 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); | 3203 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); |
3398 LocalVariable* other_var = | 3204 LocalVariable* other_var = |
3399 node->scope()->LookupVariable(Symbols::Other(), | 3205 node->scope()->LookupVariable(Symbols::Other(), |
3400 true); // Test only. | 3206 true); // Test only. |
3401 Value* other = Bind(new(Z) LoadLocalInstr(*other_var, token_pos)); | 3207 Value* other = Bind(new (Z) LoadLocalInstr(*other_var, token_pos)); |
3402 // Receiver is not a number because numbers override equality. | 3208 // Receiver is not a number because numbers override equality. |
3403 const bool kNoNumberCheck = false; | 3209 const bool kNoNumberCheck = false; |
3404 StrictCompareInstr* compare = | 3210 StrictCompareInstr* compare = new (Z) StrictCompareInstr( |
3405 new(Z) StrictCompareInstr(token_pos, | 3211 token_pos, Token::kEQ_STRICT, receiver, other, kNoNumberCheck); |
3406 Token::kEQ_STRICT, | |
3407 receiver, | |
3408 other, | |
3409 kNoNumberCheck); | |
3410 return ReturnDefinition(compare); | 3212 return ReturnDefinition(compare); |
3411 } | 3213 } |
3412 case MethodRecognizer::kStringBaseLength: | 3214 case MethodRecognizer::kStringBaseLength: |
3413 case MethodRecognizer::kStringBaseIsEmpty: { | 3215 case MethodRecognizer::kStringBaseIsEmpty: { |
3414 // Treat length loads as mutable (i.e. affected by side effects) to | 3216 // Treat length loads as mutable (i.e. affected by side effects) to |
3415 // avoid hoisting them since we can't hoist the preceding class-check. | 3217 // avoid hoisting them since we can't hoist the preceding class-check. |
3416 // This is because of externalization of strings that affects their | 3218 // This is because of externalization of strings that affects their |
3417 // class-id. | 3219 // class-id. |
3418 LoadFieldInstr* load = BuildNativeGetter( | 3220 LoadFieldInstr* load = BuildNativeGetter( |
3419 node, MethodRecognizer::kStringBaseLength, String::length_offset(), | 3221 node, MethodRecognizer::kStringBaseLength, String::length_offset(), |
3420 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); | 3222 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); |
3421 load->set_is_immutable(!FLAG_support_externalizable_strings); | 3223 load->set_is_immutable(!FLAG_support_externalizable_strings); |
3422 if (kind == MethodRecognizer::kStringBaseLength) { | 3224 if (kind == MethodRecognizer::kStringBaseLength) { |
3423 return ReturnDefinition(load); | 3225 return ReturnDefinition(load); |
3424 } | 3226 } |
3425 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); | 3227 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); |
3426 Value* zero_val = Bind(new(Z) ConstantInstr( | 3228 Value* zero_val = |
3427 Smi::ZoneHandle(Z, Smi::New(0)))); | 3229 Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0)))); |
3428 Value* load_val = Bind(load); | 3230 Value* load_val = Bind(load); |
3429 StrictCompareInstr* compare = | 3231 StrictCompareInstr* compare = new (Z) |
3430 new(Z) StrictCompareInstr(token_pos, | 3232 StrictCompareInstr(token_pos, Token::kEQ_STRICT, load_val, zero_val, |
3431 Token::kEQ_STRICT, | 3233 false); // No number check. |
3432 load_val, | |
3433 zero_val, | |
3434 false); // No number check. | |
3435 return ReturnDefinition(compare); | 3234 return ReturnDefinition(compare); |
3436 } | 3235 } |
3437 case MethodRecognizer::kGrowableArrayLength: | 3236 case MethodRecognizer::kGrowableArrayLength: |
3438 case MethodRecognizer::kObjectArrayLength: | 3237 case MethodRecognizer::kObjectArrayLength: |
3439 case MethodRecognizer::kImmutableArrayLength: | 3238 case MethodRecognizer::kImmutableArrayLength: |
3440 case MethodRecognizer::kTypedDataLength: { | 3239 case MethodRecognizer::kTypedDataLength: { |
3441 LoadFieldInstr* load = BuildNativeGetter( | 3240 LoadFieldInstr* load = |
3442 node, kind, OffsetForLengthGetter(kind), | 3241 BuildNativeGetter(node, kind, OffsetForLengthGetter(kind), |
3443 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); | 3242 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid); |
3444 load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength); | 3243 load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength); |
3445 return ReturnDefinition(load); | 3244 return ReturnDefinition(load); |
3446 } | 3245 } |
3447 case MethodRecognizer::kClassIDgetID: { | 3246 case MethodRecognizer::kClassIDgetID: { |
3448 LocalVariable* value_var = | 3247 LocalVariable* value_var = |
3449 node->scope()->LookupVariable(Symbols::Value(), true); | 3248 node->scope()->LookupVariable(Symbols::Value(), true); |
3450 Value* value = Bind(new(Z) LoadLocalInstr(*value_var, token_pos)); | 3249 Value* value = Bind(new (Z) LoadLocalInstr(*value_var, token_pos)); |
3451 LoadClassIdInstr* load = new(Z) LoadClassIdInstr(value); | 3250 LoadClassIdInstr* load = new (Z) LoadClassIdInstr(value); |
3452 return ReturnDefinition(load); | 3251 return ReturnDefinition(load); |
3453 } | 3252 } |
3454 case MethodRecognizer::kGrowableArrayCapacity: { | 3253 case MethodRecognizer::kGrowableArrayCapacity: { |
3455 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); | 3254 Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos)); |
3456 LoadFieldInstr* data_load = new(Z) LoadFieldInstr( | 3255 LoadFieldInstr* data_load = |
3457 receiver, | 3256 new (Z) LoadFieldInstr(receiver, Array::data_offset(), |
3458 Array::data_offset(), | 3257 Object::dynamic_type(), node->token_pos()); |
3459 Object::dynamic_type(), | |
3460 node->token_pos()); | |
3461 data_load->set_result_cid(kArrayCid); | 3258 data_load->set_result_cid(kArrayCid); |
3462 Value* data = Bind(data_load); | 3259 Value* data = Bind(data_load); |
3463 LoadFieldInstr* length_load = new(Z) LoadFieldInstr( | 3260 LoadFieldInstr* length_load = new (Z) LoadFieldInstr( |
3464 data, | 3261 data, Array::length_offset(), Type::ZoneHandle(Z, Type::SmiType()), |
3465 Array::length_offset(), | |
3466 Type::ZoneHandle(Z, Type::SmiType()), | |
3467 node->token_pos()); | 3262 node->token_pos()); |
3468 length_load->set_result_cid(kSmiCid); | 3263 length_load->set_result_cid(kSmiCid); |
3469 length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength); | 3264 length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength); |
3470 return ReturnDefinition(length_load); | 3265 return ReturnDefinition(length_load); |
3471 } | 3266 } |
3472 case MethodRecognizer::kObjectArrayAllocate: { | 3267 case MethodRecognizer::kObjectArrayAllocate: { |
3473 LocalVariable* type_args_parameter = | 3268 LocalVariable* type_args_parameter = node->scope()->LookupVariable( |
3474 node->scope()->LookupVariable(Symbols::TypeArgumentsParameter(), | 3269 Symbols::TypeArgumentsParameter(), true); |
3475 true); | |
3476 Value* element_type = | 3270 Value* element_type = |
3477 Bind(new(Z) LoadLocalInstr(*type_args_parameter, token_pos)); | 3271 Bind(new (Z) LoadLocalInstr(*type_args_parameter, token_pos)); |
3478 LocalVariable* length_parameter = | 3272 LocalVariable* length_parameter = |
3479 node->scope()->LookupVariable(Symbols::Length(), true); | 3273 node->scope()->LookupVariable(Symbols::Length(), true); |
3480 Value* length = | 3274 Value* length = |
3481 Bind(new(Z) LoadLocalInstr(*length_parameter, token_pos)); | 3275 Bind(new (Z) LoadLocalInstr(*length_parameter, token_pos)); |
3482 CreateArrayInstr* create_array = | 3276 CreateArrayInstr* create_array = |
3483 new CreateArrayInstr(token_pos, element_type, length); | 3277 new CreateArrayInstr(token_pos, element_type, length); |
3484 return ReturnDefinition(create_array); | 3278 return ReturnDefinition(create_array); |
3485 } | 3279 } |
3486 case MethodRecognizer::kBigint_getDigits: { | 3280 case MethodRecognizer::kBigint_getDigits: { |
3487 return ReturnDefinition(BuildNativeGetter( | 3281 return ReturnDefinition(BuildNativeGetter( |
3488 node, kind, Bigint::digits_offset(), | 3282 node, kind, Bigint::digits_offset(), Object::dynamic_type(), |
3489 Object::dynamic_type(), | |
3490 kTypedDataUint32ArrayCid)); | 3283 kTypedDataUint32ArrayCid)); |
3491 } | 3284 } |
3492 case MethodRecognizer::kBigint_getUsed: { | 3285 case MethodRecognizer::kBigint_getUsed: { |
3493 return ReturnDefinition(BuildNativeGetter( | 3286 return ReturnDefinition( |
3494 node, kind, Bigint::used_offset(), | 3287 BuildNativeGetter(node, kind, Bigint::used_offset(), |
3495 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid)); | 3288 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid)); |
3496 } | 3289 } |
3497 case MethodRecognizer::kLinkedHashMap_getIndex: { | 3290 case MethodRecognizer::kLinkedHashMap_getIndex: { |
3498 return ReturnDefinition(BuildNativeGetter( | 3291 return ReturnDefinition( |
3499 node, kind, LinkedHashMap::index_offset(), | 3292 BuildNativeGetter(node, kind, LinkedHashMap::index_offset(), |
3500 Object::dynamic_type(), | 3293 Object::dynamic_type(), kDynamicCid)); |
3501 kDynamicCid)); | |
3502 } | 3294 } |
3503 case MethodRecognizer::kLinkedHashMap_setIndex: { | 3295 case MethodRecognizer::kLinkedHashMap_setIndex: { |
3504 return ReturnDefinition(DoNativeSetterStoreValue( | 3296 return ReturnDefinition(DoNativeSetterStoreValue( |
3505 node, LinkedHashMap::index_offset(), kEmitStoreBarrier)); | 3297 node, LinkedHashMap::index_offset(), kEmitStoreBarrier)); |
3506 } | 3298 } |
3507 case MethodRecognizer::kLinkedHashMap_getData: { | 3299 case MethodRecognizer::kLinkedHashMap_getData: { |
3508 return ReturnDefinition(BuildNativeGetter( | 3300 return ReturnDefinition( |
3509 node, kind, LinkedHashMap::data_offset(), | 3301 BuildNativeGetter(node, kind, LinkedHashMap::data_offset(), |
3510 Object::dynamic_type(), | 3302 Object::dynamic_type(), kArrayCid)); |
3511 kArrayCid)); | |
3512 } | 3303 } |
3513 case MethodRecognizer::kLinkedHashMap_setData: { | 3304 case MethodRecognizer::kLinkedHashMap_setData: { |
3514 return ReturnDefinition(DoNativeSetterStoreValue( | 3305 return ReturnDefinition(DoNativeSetterStoreValue( |
3515 node, LinkedHashMap::data_offset(), kEmitStoreBarrier)); | 3306 node, LinkedHashMap::data_offset(), kEmitStoreBarrier)); |
3516 } | 3307 } |
3517 case MethodRecognizer::kLinkedHashMap_getHashMask: { | 3308 case MethodRecognizer::kLinkedHashMap_getHashMask: { |
3518 return ReturnDefinition(BuildNativeGetter( | 3309 return ReturnDefinition( |
3519 node, kind, LinkedHashMap::hash_mask_offset(), | 3310 BuildNativeGetter(node, kind, LinkedHashMap::hash_mask_offset(), |
3520 Type::ZoneHandle(Z, Type::SmiType()), | 3311 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid)); |
3521 kSmiCid)); | |
3522 } | 3312 } |
3523 case MethodRecognizer::kLinkedHashMap_setHashMask: { | 3313 case MethodRecognizer::kLinkedHashMap_setHashMask: { |
3524 // Smi field; no barrier needed. | 3314 // Smi field; no barrier needed. |
3525 return ReturnDefinition(DoNativeSetterStoreValue( | 3315 return ReturnDefinition(DoNativeSetterStoreValue( |
3526 node, LinkedHashMap::hash_mask_offset(), kNoStoreBarrier)); | 3316 node, LinkedHashMap::hash_mask_offset(), kNoStoreBarrier)); |
3527 } | 3317 } |
3528 case MethodRecognizer::kLinkedHashMap_getUsedData: { | 3318 case MethodRecognizer::kLinkedHashMap_getUsedData: { |
3529 return ReturnDefinition(BuildNativeGetter( | 3319 return ReturnDefinition( |
3530 node, kind, LinkedHashMap::used_data_offset(), | 3320 BuildNativeGetter(node, kind, LinkedHashMap::used_data_offset(), |
3531 Type::ZoneHandle(Z, Type::SmiType()), | 3321 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid)); |
3532 kSmiCid)); | |
3533 } | 3322 } |
3534 case MethodRecognizer::kLinkedHashMap_setUsedData: { | 3323 case MethodRecognizer::kLinkedHashMap_setUsedData: { |
3535 // Smi field; no barrier needed. | 3324 // Smi field; no barrier needed. |
3536 return ReturnDefinition(DoNativeSetterStoreValue( | 3325 return ReturnDefinition(DoNativeSetterStoreValue( |
3537 node, LinkedHashMap::used_data_offset(), kNoStoreBarrier)); | 3326 node, LinkedHashMap::used_data_offset(), kNoStoreBarrier)); |
3538 } | 3327 } |
3539 case MethodRecognizer::kLinkedHashMap_getDeletedKeys: { | 3328 case MethodRecognizer::kLinkedHashMap_getDeletedKeys: { |
3540 return ReturnDefinition(BuildNativeGetter( | 3329 return ReturnDefinition( |
3541 node, kind, LinkedHashMap::deleted_keys_offset(), | 3330 BuildNativeGetter(node, kind, LinkedHashMap::deleted_keys_offset(), |
3542 Type::ZoneHandle(Z, Type::SmiType()), | 3331 Type::ZoneHandle(Z, Type::SmiType()), kSmiCid)); |
3543 kSmiCid)); | |
3544 } | 3332 } |
3545 case MethodRecognizer::kLinkedHashMap_setDeletedKeys: { | 3333 case MethodRecognizer::kLinkedHashMap_setDeletedKeys: { |
3546 // Smi field; no barrier needed. | 3334 // Smi field; no barrier needed. |
3547 return ReturnDefinition(DoNativeSetterStoreValue( | 3335 return ReturnDefinition(DoNativeSetterStoreValue( |
3548 node, LinkedHashMap::deleted_keys_offset(), kNoStoreBarrier)); | 3336 node, LinkedHashMap::deleted_keys_offset(), kNoStoreBarrier)); |
3549 } | 3337 } |
3550 case MethodRecognizer::kBigint_getNeg: { | 3338 case MethodRecognizer::kBigint_getNeg: { |
3551 return ReturnDefinition(BuildNativeGetter( | 3339 return ReturnDefinition( |
3552 node, kind, Bigint::neg_offset(), | 3340 BuildNativeGetter(node, kind, Bigint::neg_offset(), |
3553 Type::ZoneHandle(Z, Type::BoolType()), kBoolCid)); | 3341 Type::ZoneHandle(Z, Type::BoolType()), kBoolCid)); |
3554 } | 3342 } |
3555 default: | 3343 default: |
3556 break; | 3344 break; |
3557 } | 3345 } |
3558 } | 3346 } |
3559 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode"); | 3347 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode"); |
3560 NativeCallInstr* native_call = new(Z) NativeCallInstr(node); | 3348 NativeCallInstr* native_call = new (Z) NativeCallInstr(node); |
3561 ReturnDefinition(native_call); | 3349 ReturnDefinition(native_call); |
3562 } | 3350 } |
3563 | 3351 |
3564 | 3352 |
3565 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { | 3353 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { |
3566 // PrimaryNodes are temporary during parsing. | 3354 // PrimaryNodes are temporary during parsing. |
3567 UNREACHABLE(); | 3355 UNREACHABLE(); |
3568 } | 3356 } |
3569 | 3357 |
3570 | 3358 |
(...skipping 18 matching lines...) Expand all Loading... |
3589 // variables, or for generated code that has no source position. | 3377 // variables, or for generated code that has no source position. |
3590 if (FLAG_support_debugger) { | 3378 if (FLAG_support_debugger) { |
3591 AstNode* rhs = node->value(); | 3379 AstNode* rhs = node->value(); |
3592 if (rhs->IsAssignableNode()) { | 3380 if (rhs->IsAssignableNode()) { |
3593 rhs = rhs->AsAssignableNode()->expr(); | 3381 rhs = rhs->AsAssignableNode()->expr(); |
3594 } | 3382 } |
3595 if ((rhs->IsLiteralNode() || | 3383 if ((rhs->IsLiteralNode() || |
3596 (rhs->IsLoadLocalNode() && | 3384 (rhs->IsLoadLocalNode() && |
3597 !rhs->AsLoadLocalNode()->local().IsInternal()) || | 3385 !rhs->AsLoadLocalNode()->local().IsInternal()) || |
3598 rhs->IsClosureNode()) && | 3386 rhs->IsClosureNode()) && |
3599 !node->local().IsInternal() && | 3387 !node->local().IsInternal() && node->token_pos().IsDebugPause()) { |
3600 node->token_pos().IsDebugPause()) { | 3388 AddInstruction(new (Z) DebugStepCheckInstr( |
3601 AddInstruction(new(Z) DebugStepCheckInstr( | |
3602 node->token_pos(), RawPcDescriptors::kRuntimeCall)); | 3389 node->token_pos(), RawPcDescriptors::kRuntimeCall)); |
3603 } | 3390 } |
3604 } | 3391 } |
3605 | 3392 |
3606 ValueGraphVisitor for_value(owner()); | 3393 ValueGraphVisitor for_value(owner()); |
3607 node->value()->Visit(&for_value); | 3394 node->value()->Visit(&for_value); |
3608 Append(for_value); | 3395 Append(for_value); |
3609 Value* store_value = for_value.value(); | 3396 Value* store_value = for_value.value(); |
3610 if (Isolate::Current()->type_checks()) { | 3397 if (Isolate::Current()->type_checks()) { |
3611 store_value = BuildAssignableValue(node->value()->token_pos(), | 3398 store_value = |
3612 store_value, | 3399 BuildAssignableValue(node->value()->token_pos(), store_value, |
3613 node->local().type(), | 3400 node->local().type(), node->local().name()); |
3614 node->local().name()); | |
3615 } | 3401 } |
3616 Definition* store = BuildStoreLocal(node->local(), | 3402 Definition* store = |
3617 store_value, | 3403 BuildStoreLocal(node->local(), store_value, node->token_pos()); |
3618 node->token_pos()); | |
3619 ReturnDefinition(store); | 3404 ReturnDefinition(store); |
3620 } | 3405 } |
3621 | 3406 |
3622 | 3407 |
3623 void EffectGraphVisitor::VisitLoadInstanceFieldNode( | 3408 void EffectGraphVisitor::VisitLoadInstanceFieldNode( |
3624 LoadInstanceFieldNode* node) { | 3409 LoadInstanceFieldNode* node) { |
3625 ValueGraphVisitor for_instance(owner()); | 3410 ValueGraphVisitor for_instance(owner()); |
3626 node->instance()->Visit(&for_instance); | 3411 node->instance()->Visit(&for_instance); |
3627 Append(for_instance); | 3412 Append(for_instance); |
3628 LoadFieldInstr* load = new(Z) LoadFieldInstr( | 3413 LoadFieldInstr* load = new (Z) LoadFieldInstr( |
3629 for_instance.value(), | 3414 for_instance.value(), &node->field(), |
3630 &node->field(), | 3415 AbstractType::ZoneHandle(Z, node->field().type()), node->token_pos()); |
3631 AbstractType::ZoneHandle(Z, node->field().type()), | |
3632 node->token_pos()); | |
3633 if (node->field().guarded_cid() != kIllegalCid) { | 3416 if (node->field().guarded_cid() != kIllegalCid) { |
3634 if (!node->field().is_nullable() || | 3417 if (!node->field().is_nullable() || |
3635 (node->field().guarded_cid() == kNullCid)) { | 3418 (node->field().guarded_cid() == kNullCid)) { |
3636 load->set_result_cid(node->field().guarded_cid()); | 3419 load->set_result_cid(node->field().guarded_cid()); |
3637 } | 3420 } |
3638 owner()->parsed_function().AddToGuardedFields(&node->field()); | 3421 owner()->parsed_function().AddToGuardedFields(&node->field()); |
3639 } | 3422 } |
3640 ReturnDefinition(load); | 3423 ReturnDefinition(load); |
3641 } | 3424 } |
3642 | 3425 |
3643 | 3426 |
3644 void EffectGraphVisitor::VisitStoreInstanceFieldNode( | 3427 void EffectGraphVisitor::VisitStoreInstanceFieldNode( |
3645 StoreInstanceFieldNode* node) { | 3428 StoreInstanceFieldNode* node) { |
3646 const TokenPosition token_pos = node->token_pos(); | 3429 const TokenPosition token_pos = node->token_pos(); |
3647 ValueGraphVisitor for_instance(owner()); | 3430 ValueGraphVisitor for_instance(owner()); |
3648 node->instance()->Visit(&for_instance); | 3431 node->instance()->Visit(&for_instance); |
3649 Append(for_instance); | 3432 Append(for_instance); |
3650 ValueGraphVisitor for_value(owner()); | 3433 ValueGraphVisitor for_value(owner()); |
3651 node->value()->Visit(&for_value); | 3434 node->value()->Visit(&for_value); |
3652 Append(for_value); | 3435 Append(for_value); |
3653 Value* store_value = for_value.value(); | 3436 Value* store_value = for_value.value(); |
3654 if (Isolate::Current()->type_checks()) { | 3437 if (Isolate::Current()->type_checks()) { |
3655 const AbstractType& type = | 3438 const AbstractType& type = |
3656 AbstractType::ZoneHandle(Z, node->field().type()); | 3439 AbstractType::ZoneHandle(Z, node->field().type()); |
3657 const String& dst_name = String::ZoneHandle(Z, node->field().name()); | 3440 const String& dst_name = String::ZoneHandle(Z, node->field().name()); |
3658 store_value = BuildAssignableValue(node->value()->token_pos(), | 3441 store_value = BuildAssignableValue(node->value()->token_pos(), store_value, |
3659 store_value, | 3442 type, dst_name); |
3660 type, | |
3661 dst_name); | |
3662 } | 3443 } |
3663 | 3444 |
3664 if (FLAG_use_field_guards) { | 3445 if (FLAG_use_field_guards) { |
3665 store_value = Bind(BuildStoreExprTemp(store_value, token_pos)); | 3446 store_value = Bind(BuildStoreExprTemp(store_value, token_pos)); |
3666 GuardFieldClassInstr* guard_field_class = | 3447 GuardFieldClassInstr* guard_field_class = new (Z) GuardFieldClassInstr( |
3667 new(Z) GuardFieldClassInstr(store_value, | 3448 store_value, node->field(), thread()->GetNextDeoptId()); |
3668 node->field(), | |
3669 thread()->GetNextDeoptId()); | |
3670 AddInstruction(guard_field_class); | 3449 AddInstruction(guard_field_class); |
3671 store_value = Bind(BuildLoadExprTemp(token_pos)); | 3450 store_value = Bind(BuildLoadExprTemp(token_pos)); |
3672 GuardFieldLengthInstr* guard_field_length = | 3451 GuardFieldLengthInstr* guard_field_length = new (Z) GuardFieldLengthInstr( |
3673 new(Z) GuardFieldLengthInstr(store_value, | 3452 store_value, node->field(), thread()->GetNextDeoptId()); |
3674 node->field(), | |
3675 thread()->GetNextDeoptId()); | |
3676 AddInstruction(guard_field_length); | 3453 AddInstruction(guard_field_length); |
3677 store_value = Bind(BuildLoadExprTemp(token_pos)); | 3454 store_value = Bind(BuildLoadExprTemp(token_pos)); |
3678 } | 3455 } |
3679 StoreInstanceFieldInstr* store = | 3456 StoreInstanceFieldInstr* store = new (Z) |
3680 new(Z) StoreInstanceFieldInstr(node->field(), | 3457 StoreInstanceFieldInstr(node->field(), for_instance.value(), store_value, |
3681 for_instance.value(), | 3458 kEmitStoreBarrier, token_pos); |
3682 store_value, | |
3683 kEmitStoreBarrier, | |
3684 token_pos); | |
3685 // Maybe initializing unboxed store. | 3459 // Maybe initializing unboxed store. |
3686 store->set_is_initialization(node->is_initializer()); | 3460 store->set_is_initialization(node->is_initializer()); |
3687 ReturnDefinition(store); | 3461 ReturnDefinition(store); |
3688 } | 3462 } |
3689 | 3463 |
3690 | 3464 |
3691 void EffectGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { | 3465 void EffectGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) { |
3692 const TokenPosition token_pos = node->token_pos(); | 3466 const TokenPosition token_pos = node->token_pos(); |
3693 if (node->field().is_const()) { | 3467 if (node->field().is_const()) { |
3694 ASSERT(node->field().StaticValue() != Object::sentinel().raw()); | 3468 ASSERT(node->field().StaticValue() != Object::sentinel().raw()); |
3695 ASSERT(node->field().StaticValue() != | 3469 ASSERT(node->field().StaticValue() != Object::transition_sentinel().raw()); |
3696 Object::transition_sentinel().raw()); | 3470 Definition* result = new (Z) ConstantInstr( |
3697 Definition* result = new(Z) ConstantInstr( | |
3698 Instance::ZoneHandle(Z, node->field().StaticValue()), token_pos); | 3471 Instance::ZoneHandle(Z, node->field().StaticValue()), token_pos); |
3699 return ReturnDefinition(result); | 3472 return ReturnDefinition(result); |
3700 } | 3473 } |
3701 Value* field_value = Bind(new(Z) ConstantInstr( | 3474 Value* field_value = Bind(new (Z) ConstantInstr( |
3702 Field::ZoneHandle(Z, node->field().Original()), token_pos)); | 3475 Field::ZoneHandle(Z, node->field().Original()), token_pos)); |
3703 LoadStaticFieldInstr* load = | 3476 LoadStaticFieldInstr* load = |
3704 new(Z) LoadStaticFieldInstr(field_value, token_pos); | 3477 new (Z) LoadStaticFieldInstr(field_value, token_pos); |
3705 ReturnDefinition(load); | 3478 ReturnDefinition(load); |
3706 } | 3479 } |
3707 | 3480 |
3708 | 3481 |
3709 Definition* EffectGraphVisitor::BuildStoreStaticField( | 3482 Definition* EffectGraphVisitor::BuildStoreStaticField( |
3710 StoreStaticFieldNode* node, | 3483 StoreStaticFieldNode* node, |
3711 bool result_is_needed, | 3484 bool result_is_needed, |
3712 TokenPosition token_pos) { | 3485 TokenPosition token_pos) { |
3713 if (FLAG_support_debugger) { | 3486 if (FLAG_support_debugger) { |
3714 // If the right hand side is an expression that does not contain | 3487 // If the right hand side is an expression that does not contain |
3715 // a safe point for the debugger to stop, add an explicit stub | 3488 // a safe point for the debugger to stop, add an explicit stub |
3716 // call. | 3489 // call. |
3717 AstNode* rhs = node->value(); | 3490 AstNode* rhs = node->value(); |
3718 if (rhs->IsAssignableNode()) { | 3491 if (rhs->IsAssignableNode()) { |
3719 rhs = rhs->AsAssignableNode()->expr(); | 3492 rhs = rhs->AsAssignableNode()->expr(); |
3720 } | 3493 } |
3721 if ((rhs->IsLiteralNode() || | 3494 if ((rhs->IsLiteralNode() || rhs->IsLoadLocalNode() || |
3722 rhs->IsLoadLocalNode() || | |
3723 rhs->IsClosureNode()) && | 3495 rhs->IsClosureNode()) && |
3724 node->token_pos().IsDebugPause()) { | 3496 node->token_pos().IsDebugPause()) { |
3725 AddInstruction(new(Z) DebugStepCheckInstr( | 3497 AddInstruction(new (Z) DebugStepCheckInstr( |
3726 node->token_pos(), RawPcDescriptors::kRuntimeCall)); | 3498 node->token_pos(), RawPcDescriptors::kRuntimeCall)); |
3727 } | 3499 } |
3728 } | 3500 } |
3729 | 3501 |
3730 ValueGraphVisitor for_value(owner()); | 3502 ValueGraphVisitor for_value(owner()); |
3731 node->value()->Visit(&for_value); | 3503 node->value()->Visit(&for_value); |
3732 Append(for_value); | 3504 Append(for_value); |
3733 Value* store_value = NULL; | 3505 Value* store_value = NULL; |
3734 if (result_is_needed) { | 3506 if (result_is_needed) { |
3735 store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); | 3507 store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); |
3736 } else { | 3508 } else { |
3737 store_value = for_value.value(); | 3509 store_value = for_value.value(); |
3738 } | 3510 } |
3739 StoreStaticFieldInstr* store = | 3511 StoreStaticFieldInstr* store = |
3740 new(Z) StoreStaticFieldInstr(node->field(), store_value, token_pos); | 3512 new (Z) StoreStaticFieldInstr(node->field(), store_value, token_pos); |
3741 | 3513 |
3742 if (result_is_needed) { | 3514 if (result_is_needed) { |
3743 Do(store); | 3515 Do(store); |
3744 return BuildLoadExprTemp(token_pos); | 3516 return BuildLoadExprTemp(token_pos); |
3745 } else { | 3517 } else { |
3746 return store; | 3518 return store; |
3747 } | 3519 } |
3748 } | 3520 } |
3749 | 3521 |
3750 | 3522 |
3751 void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { | 3523 void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
3752 ReturnDefinition( | 3524 ReturnDefinition( |
3753 BuildStoreStaticField(node, kResultNotNeeded, node->token_pos())); | 3525 BuildStoreStaticField(node, kResultNotNeeded, node->token_pos())); |
3754 } | 3526 } |
3755 | 3527 |
3756 | 3528 |
3757 void ValueGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { | 3529 void ValueGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
3758 ReturnDefinition( | 3530 ReturnDefinition( |
3759 BuildStoreStaticField(node, kResultNeeded, node->token_pos())); | 3531 BuildStoreStaticField(node, kResultNeeded, node->token_pos())); |
3760 } | 3532 } |
3761 | 3533 |
3762 | 3534 |
3763 void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { | 3535 void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) { |
3764 Function* super_function = NULL; | 3536 Function* super_function = NULL; |
3765 if (node->IsSuperLoad()) { | 3537 if (node->IsSuperLoad()) { |
3766 // Resolve the load indexed operator in the super class. | 3538 // Resolve the load indexed operator in the super class. |
3767 super_function = &Function::ZoneHandle(Z, Resolver::ResolveDynamicAnyArgs(Z, | 3539 super_function = &Function::ZoneHandle( |
3768 node->super_class(), Symbols::IndexToken())); | 3540 Z, Resolver::ResolveDynamicAnyArgs(Z, node->super_class(), |
| 3541 Symbols::IndexToken())); |
3769 if (super_function->IsNull()) { | 3542 if (super_function->IsNull()) { |
3770 // Could not resolve super operator. Generate call noSuchMethod() of the | 3543 // Could not resolve super operator. Generate call noSuchMethod() of the |
3771 // super class instead. | 3544 // super class instead. |
3772 ArgumentListNode* arguments = new(Z) ArgumentListNode(node->token_pos()); | 3545 ArgumentListNode* arguments = new (Z) ArgumentListNode(node->token_pos()); |
3773 arguments->Add(node->array()); | 3546 arguments->Add(node->array()); |
3774 arguments->Add(node->index_expr()); | 3547 arguments->Add(node->index_expr()); |
3775 StaticCallInstr* call = | 3548 StaticCallInstr* call = BuildStaticNoSuchMethodCall( |
3776 BuildStaticNoSuchMethodCall(node->super_class(), | 3549 node->super_class(), node->array(), Symbols::IndexToken(), arguments, |
3777 node->array(), | 3550 false, // Don't save last arg. |
3778 Symbols::IndexToken(), | 3551 true); // Super invocation. |
3779 arguments, | |
3780 false, // Don't save last arg. | |
3781 true); // Super invocation. | |
3782 ReturnDefinition(call); | 3552 ReturnDefinition(call); |
3783 return; | 3553 return; |
3784 } | 3554 } |
3785 } | 3555 } |
3786 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3556 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3787 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 3557 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
3788 ValueGraphVisitor for_array(owner()); | 3558 ValueGraphVisitor for_array(owner()); |
3789 node->array()->Visit(&for_array); | 3559 node->array()->Visit(&for_array); |
3790 Append(for_array); | 3560 Append(for_array); |
3791 arguments->Add(PushArgument(for_array.value())); | 3561 arguments->Add(PushArgument(for_array.value())); |
3792 | 3562 |
3793 ValueGraphVisitor for_index(owner()); | 3563 ValueGraphVisitor for_index(owner()); |
3794 node->index_expr()->Visit(&for_index); | 3564 node->index_expr()->Visit(&for_index); |
3795 Append(for_index); | 3565 Append(for_index); |
3796 arguments->Add(PushArgument(for_index.value())); | 3566 arguments->Add(PushArgument(for_index.value())); |
3797 | 3567 |
3798 if (super_function != NULL) { | 3568 if (super_function != NULL) { |
3799 // Generate static call to super operator. | 3569 // Generate static call to super operator. |
3800 StaticCallInstr* load = new(Z) StaticCallInstr(node->token_pos(), | 3570 StaticCallInstr* load = new (Z) StaticCallInstr( |
3801 *super_function, | 3571 node->token_pos(), *super_function, Object::null_array(), arguments, |
3802 Object::null_array(), | 3572 owner()->ic_data_array()); |
3803 arguments, | |
3804 owner()->ic_data_array()); | |
3805 ReturnDefinition(load); | 3573 ReturnDefinition(load); |
3806 } else { | 3574 } else { |
3807 // Generate dynamic call to index operator. | 3575 // Generate dynamic call to index operator. |
3808 const intptr_t checked_argument_count = 1; | 3576 const intptr_t checked_argument_count = 1; |
3809 InstanceCallInstr* load = new(Z) InstanceCallInstr( | 3577 InstanceCallInstr* load = new (Z) InstanceCallInstr( |
3810 node->token_pos(), | 3578 node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments, |
3811 Symbols::IndexToken(), | 3579 Object::null_array(), checked_argument_count, owner()->ic_data_array()); |
3812 Token::kINDEX, | |
3813 arguments, | |
3814 Object::null_array(), | |
3815 checked_argument_count, | |
3816 owner()->ic_data_array()); | |
3817 ReturnDefinition(load); | 3580 ReturnDefinition(load); |
3818 } | 3581 } |
3819 } | 3582 } |
3820 | 3583 |
3821 | 3584 |
3822 Definition* EffectGraphVisitor::BuildStoreIndexedValues( | 3585 Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node, |
3823 StoreIndexedNode* node, | 3586 bool result_is_needed) { |
3824 bool result_is_needed) { | |
3825 Function* super_function = NULL; | 3587 Function* super_function = NULL; |
3826 const TokenPosition token_pos = node->token_pos(); | 3588 const TokenPosition token_pos = node->token_pos(); |
3827 if (node->IsSuperStore()) { | 3589 if (node->IsSuperStore()) { |
3828 // Resolve the store indexed operator in the super class. | 3590 // Resolve the store indexed operator in the super class. |
3829 super_function = &Function::ZoneHandle(Z, Resolver::ResolveDynamicAnyArgs(Z, | 3591 super_function = &Function::ZoneHandle( |
3830 node->super_class(), Symbols::AssignIndexToken())); | 3592 Z, Resolver::ResolveDynamicAnyArgs(Z, node->super_class(), |
| 3593 Symbols::AssignIndexToken())); |
3831 if (super_function->IsNull()) { | 3594 if (super_function->IsNull()) { |
3832 // Could not resolve super operator. Generate call noSuchMethod() of the | 3595 // Could not resolve super operator. Generate call noSuchMethod() of the |
3833 // super class instead. | 3596 // super class instead. |
3834 ArgumentListNode* arguments = new(Z) ArgumentListNode(token_pos); | 3597 ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos); |
3835 arguments->Add(node->array()); | 3598 arguments->Add(node->array()); |
3836 arguments->Add(node->index_expr()); | 3599 arguments->Add(node->index_expr()); |
3837 arguments->Add(node->value()); | 3600 arguments->Add(node->value()); |
3838 StaticCallInstr* call = BuildStaticNoSuchMethodCall( | 3601 StaticCallInstr* call = BuildStaticNoSuchMethodCall( |
3839 node->super_class(), | 3602 node->super_class(), node->array(), Symbols::AssignIndexToken(), |
3840 node->array(), | |
3841 Symbols::AssignIndexToken(), | |
3842 arguments, | 3603 arguments, |
3843 result_is_needed, // Save last arg if result is needed. | 3604 result_is_needed, // Save last arg if result is needed. |
3844 true); // Super invocation. | 3605 true); // Super invocation. |
3845 if (result_is_needed) { | 3606 if (result_is_needed) { |
3846 Do(call); | 3607 Do(call); |
3847 // BuildStaticNoSuchMethodCall stores the value in expression_temp. | 3608 // BuildStaticNoSuchMethodCall stores the value in expression_temp. |
3848 return BuildLoadExprTemp(token_pos); | 3609 return BuildLoadExprTemp(token_pos); |
3849 } else { | 3610 } else { |
3850 return call; | 3611 return call; |
3851 } | 3612 } |
3852 } | 3613 } |
3853 } | 3614 } |
3854 | 3615 |
3855 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 3616 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
3856 new(Z) ZoneGrowableArray<PushArgumentInstr*>(3); | 3617 new (Z) ZoneGrowableArray<PushArgumentInstr*>(3); |
3857 ValueGraphVisitor for_array(owner()); | 3618 ValueGraphVisitor for_array(owner()); |
3858 node->array()->Visit(&for_array); | 3619 node->array()->Visit(&for_array); |
3859 Append(for_array); | 3620 Append(for_array); |
3860 arguments->Add(PushArgument(for_array.value())); | 3621 arguments->Add(PushArgument(for_array.value())); |
3861 | 3622 |
3862 ValueGraphVisitor for_index(owner()); | 3623 ValueGraphVisitor for_index(owner()); |
3863 node->index_expr()->Visit(&for_index); | 3624 node->index_expr()->Visit(&for_index); |
3864 Append(for_index); | 3625 Append(for_index); |
3865 arguments->Add(PushArgument(for_index.value())); | 3626 arguments->Add(PushArgument(for_index.value())); |
3866 | 3627 |
3867 ValueGraphVisitor for_value(owner()); | 3628 ValueGraphVisitor for_value(owner()); |
3868 node->value()->Visit(&for_value); | 3629 node->value()->Visit(&for_value); |
3869 Append(for_value); | 3630 Append(for_value); |
3870 Value* value = NULL; | 3631 Value* value = NULL; |
3871 if (result_is_needed) { | 3632 if (result_is_needed) { |
3872 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); | 3633 value = Bind(BuildStoreExprTemp(for_value.value(), token_pos)); |
3873 } else { | 3634 } else { |
3874 value = for_value.value(); | 3635 value = for_value.value(); |
3875 } | 3636 } |
3876 arguments->Add(PushArgument(value)); | 3637 arguments->Add(PushArgument(value)); |
3877 | 3638 |
3878 if (super_function != NULL) { | 3639 if (super_function != NULL) { |
3879 // Generate static call to super operator []=. | 3640 // Generate static call to super operator []=. |
3880 | 3641 |
3881 StaticCallInstr* store = | 3642 StaticCallInstr* store = new (Z) |
3882 new(Z) StaticCallInstr(token_pos, | 3643 StaticCallInstr(token_pos, *super_function, Object::null_array(), |
3883 *super_function, | 3644 arguments, owner()->ic_data_array()); |
3884 Object::null_array(), | |
3885 arguments, | |
3886 owner()->ic_data_array()); | |
3887 if (result_is_needed) { | 3645 if (result_is_needed) { |
3888 Do(store); | 3646 Do(store); |
3889 return BuildLoadExprTemp(token_pos); | 3647 return BuildLoadExprTemp(token_pos); |
3890 } else { | 3648 } else { |
3891 return store; | 3649 return store; |
3892 } | 3650 } |
3893 } else { | 3651 } else { |
3894 // Generate dynamic call to operator []=. | 3652 // Generate dynamic call to operator []=. |
3895 const intptr_t checked_argument_count = 2; // Do not check for value type. | 3653 const intptr_t checked_argument_count = 2; // Do not check for value type. |
3896 InstanceCallInstr* store = | 3654 InstanceCallInstr* store = new (Z) InstanceCallInstr( |
3897 new(Z) InstanceCallInstr(token_pos, | 3655 token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments, |
3898 Symbols::AssignIndexToken(), | 3656 Object::null_array(), checked_argument_count, owner()->ic_data_array()); |
3899 Token::kASSIGN_INDEX, | |
3900 arguments, | |
3901 Object::null_array(), | |
3902 checked_argument_count, | |
3903 owner()->ic_data_array()); | |
3904 if (result_is_needed) { | 3657 if (result_is_needed) { |
3905 Do(store); | 3658 Do(store); |
3906 return BuildLoadExprTemp(token_pos); | 3659 return BuildLoadExprTemp(token_pos); |
3907 } else { | 3660 } else { |
3908 return store; | 3661 return store; |
3909 } | 3662 } |
3910 } | 3663 } |
3911 } | 3664 } |
3912 | 3665 |
3913 | 3666 |
3914 void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { | 3667 void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
3915 ReturnDefinition(BuildStoreIndexedValues(node, kResultNotNeeded)); | 3668 ReturnDefinition(BuildStoreIndexedValues(node, kResultNotNeeded)); |
3916 } | 3669 } |
3917 | 3670 |
3918 | 3671 |
3919 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { | 3672 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
3920 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); | 3673 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); |
3921 } | 3674 } |
3922 | 3675 |
3923 | 3676 |
3924 bool EffectGraphVisitor::HasContextScope() const { | 3677 bool EffectGraphVisitor::HasContextScope() const { |
3925 const ContextScope& context_scope = ContextScope::Handle( | 3678 const ContextScope& context_scope = |
3926 owner()->function().context_scope()); | 3679 ContextScope::Handle(owner()->function().context_scope()); |
3927 return !context_scope.IsNull() && (context_scope.num_variables() > 0); | 3680 return !context_scope.IsNull() && (context_scope.num_variables() > 0); |
3928 } | 3681 } |
3929 | 3682 |
3930 | 3683 |
3931 void EffectGraphVisitor::UnchainContexts(intptr_t n) { | 3684 void EffectGraphVisitor::UnchainContexts(intptr_t n) { |
3932 // TODO(johnmccutchan): Pass this in. | 3685 // TODO(johnmccutchan): Pass this in. |
3933 const TokenPosition token_pos = TokenPosition::kContext; | 3686 const TokenPosition token_pos = TokenPosition::kContext; |
3934 if (n > 0) { | 3687 if (n > 0) { |
3935 Value* context = Bind(BuildCurrentContext(token_pos)); | 3688 Value* context = Bind(BuildCurrentContext(token_pos)); |
3936 while (n-- > 0) { | 3689 while (n-- > 0) { |
3937 context = Bind( | 3690 context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(), |
3938 new(Z) LoadFieldInstr(context, | 3691 // Not an instance, no type. |
3939 Context::parent_offset(), | 3692 Type::ZoneHandle(Z, Type::null()), |
3940 // Not an instance, no type. | 3693 token_pos)); |
3941 Type::ZoneHandle(Z, Type::null()), | |
3942 token_pos)); | |
3943 } | 3694 } |
3944 Do(BuildStoreContext(context, token_pos)); | 3695 Do(BuildStoreContext(context, token_pos)); |
3945 } | 3696 } |
3946 } | 3697 } |
3947 | 3698 |
3948 | 3699 |
3949 void EffectGraphVisitor::AdjustContextLevel(LocalScope* target_scope) { | 3700 void EffectGraphVisitor::AdjustContextLevel(LocalScope* target_scope) { |
3950 ASSERT(target_scope != NULL); | 3701 ASSERT(target_scope != NULL); |
3951 intptr_t target_context_level = 0; | 3702 intptr_t target_context_level = 0; |
3952 if (target_scope->num_context_variables() > 0) { | 3703 if (target_scope->num_context_variables() > 0) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3984 const bool is_top_level_sequence = | 3735 const bool is_top_level_sequence = |
3985 node == owner()->parsed_function().node_sequence(); | 3736 node == owner()->parsed_function().node_sequence(); |
3986 // The outermost function sequence cannot contain a label. | 3737 // The outermost function sequence cannot contain a label. |
3987 ASSERT((node->label() == NULL) || !is_top_level_sequence); | 3738 ASSERT((node->label() == NULL) || !is_top_level_sequence); |
3988 NestedBlock nested_block(owner(), node); | 3739 NestedBlock nested_block(owner(), node); |
3989 | 3740 |
3990 if (num_context_variables > 0) { | 3741 if (num_context_variables > 0) { |
3991 // The local scope declares variables that are captured. | 3742 // The local scope declares variables that are captured. |
3992 // Allocate and chain a new context (Except don't chain when at the function | 3743 // Allocate and chain a new context (Except don't chain when at the function |
3993 // entry if the function does not capture any variables from outer scopes). | 3744 // entry if the function does not capture any variables from outer scopes). |
3994 Value* allocated_context = | 3745 Value* allocated_context = Bind( |
3995 Bind(new(Z) AllocateContextInstr(node->token_pos(), | 3746 new (Z) AllocateContextInstr(node->token_pos(), num_context_variables)); |
3996 num_context_variables)); | 3747 { |
3997 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); | 3748 LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); |
3998 if (!is_top_level_sequence || HasContextScope()) { | 3749 if (!is_top_level_sequence || HasContextScope()) { |
3999 ASSERT(is_top_level_sequence || | 3750 ASSERT(is_top_level_sequence || |
4000 (nested_block.ContextLevel() == | 3751 (nested_block.ContextLevel() == |
4001 nested_block.outer()->ContextLevel() + 1)); | 3752 nested_block.outer()->ContextLevel() + 1)); |
4002 Value* tmp_val = Bind( | 3753 Value* tmp_val = |
4003 new(Z) LoadLocalInstr(*tmp_var, node->token_pos())); | 3754 Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos())); |
4004 Value* parent_context = Bind(BuildCurrentContext(node->token_pos())); | 3755 Value* parent_context = Bind(BuildCurrentContext(node->token_pos())); |
4005 Do(new(Z) StoreInstanceFieldInstr(Context::parent_offset(), | 3756 Do(new (Z) StoreInstanceFieldInstr(Context::parent_offset(), tmp_val, |
4006 tmp_val, | 3757 parent_context, kEmitStoreBarrier, |
4007 parent_context, | 3758 node->token_pos())); |
4008 kEmitStoreBarrier, | |
4009 node->token_pos())); | |
4010 } | 3759 } |
4011 Do(BuildStoreContext( | 3760 Do(BuildStoreContext(Bind(ExitTempLocalScope(allocated_context)), |
4012 Bind(ExitTempLocalScope(allocated_context)), | 3761 node->token_pos())); |
4013 node->token_pos())); | |
4014 } | 3762 } |
4015 | 3763 |
4016 // If this node_sequence is the body of the function being compiled, copy | 3764 // If this node_sequence is the body of the function being compiled, copy |
4017 // the captured parameters from the frame into the context. | 3765 // the captured parameters from the frame into the context. |
4018 if (is_top_level_sequence) { | 3766 if (is_top_level_sequence) { |
4019 ASSERT(scope->context_level() == 1); | 3767 ASSERT(scope->context_level() == 1); |
4020 const int num_params = function.NumParameters(); | 3768 const int num_params = function.NumParameters(); |
4021 int param_frame_index = (num_params == function.num_fixed_parameters()) ? | 3769 int param_frame_index = (num_params == function.num_fixed_parameters()) |
4022 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; | 3770 ? (kParamEndSlotFromFp + num_params) |
| 3771 : kFirstLocalSlotFromFp; |
4023 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { | 3772 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { |
4024 const LocalVariable& parameter = *scope->VariableAt(pos); | 3773 const LocalVariable& parameter = *scope->VariableAt(pos); |
4025 ASSERT(parameter.owner() == scope); | 3774 ASSERT(parameter.owner() == scope); |
4026 if (parameter.is_captured()) { | 3775 if (parameter.is_captured()) { |
4027 // Create a temporary local describing the original position. | 3776 // Create a temporary local describing the original position. |
4028 const String& temp_name = Symbols::TempParam(); | 3777 const String& temp_name = Symbols::TempParam(); |
4029 LocalVariable* temp_local = new(Z) LocalVariable( | 3778 LocalVariable* temp_local = |
4030 TokenPosition::kNoSource, // Token index. | 3779 new (Z) LocalVariable(TokenPosition::kNoSource, // Token index. |
4031 TokenPosition::kNoSource, // Token index. | 3780 TokenPosition::kNoSource, // Token index. |
4032 temp_name, | 3781 temp_name, |
4033 Object::dynamic_type()); // Type. | 3782 Object::dynamic_type()); // Type. |
4034 temp_local->set_index(param_frame_index); | 3783 temp_local->set_index(param_frame_index); |
4035 | 3784 |
4036 // Mark this local as captured parameter so that the optimizer | 3785 // Mark this local as captured parameter so that the optimizer |
4037 // correctly handles these when compiling try-catch: Captured | 3786 // correctly handles these when compiling try-catch: Captured |
4038 // parameters are not in the stack environment, therefore they | 3787 // parameters are not in the stack environment, therefore they |
4039 // must be skipped when emitting sync-code in try-blocks. | 3788 // must be skipped when emitting sync-code in try-blocks. |
4040 temp_local->set_is_captured_parameter(true); | 3789 temp_local->set_is_captured_parameter(true); |
4041 | 3790 |
4042 // Copy parameter from local frame to current context. | 3791 // Copy parameter from local frame to current context. |
4043 Value* load = Bind(BuildLoadLocal(*temp_local, node->token_pos())); | 3792 Value* load = Bind(BuildLoadLocal(*temp_local, node->token_pos())); |
4044 Do(BuildStoreLocal(parameter, load, ST(node->token_pos()))); | 3793 Do(BuildStoreLocal(parameter, load, ST(node->token_pos()))); |
4045 // Write NULL to the source location to detect buggy accesses and | 3794 // Write NULL to the source location to detect buggy accesses and |
4046 // allow GC of passed value if it gets overwritten by a new value in | 3795 // allow GC of passed value if it gets overwritten by a new value in |
4047 // the function. | 3796 // the function. |
4048 Value* null_constant = Bind(new(Z) ConstantInstr( | 3797 Value* null_constant = Bind( |
4049 Object::ZoneHandle(Z, Object::null()))); | 3798 new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()))); |
4050 Do(BuildStoreLocal(*temp_local, | 3799 Do(BuildStoreLocal(*temp_local, null_constant, |
4051 null_constant, | |
4052 ST(node->token_pos()))); | 3800 ST(node->token_pos()))); |
4053 } | 3801 } |
4054 } | 3802 } |
4055 } | 3803 } |
4056 } | 3804 } |
4057 | 3805 |
4058 if (FLAG_support_debugger && | 3806 if (FLAG_support_debugger && is_top_level_sequence && |
4059 is_top_level_sequence && | |
4060 function.is_debuggable()) { | 3807 function.is_debuggable()) { |
4061 // Place a debug check at method entry to ensure breaking on a method always | 3808 // Place a debug check at method entry to ensure breaking on a method always |
4062 // happens, even if there are no assignments/calls/runtimecalls in the first | 3809 // happens, even if there are no assignments/calls/runtimecalls in the first |
4063 // basic block. Place this check at the last parameter to ensure parameters | 3810 // basic block. Place this check at the last parameter to ensure parameters |
4064 // are in scope in the debugger at method entry. | 3811 // are in scope in the debugger at method entry. |
4065 const int num_params = function.NumParameters(); | 3812 const int num_params = function.NumParameters(); |
4066 TokenPosition check_pos = TokenPosition::kNoSource; | 3813 TokenPosition check_pos = TokenPosition::kNoSource; |
4067 if (num_params > 0) { | 3814 if (num_params > 0) { |
4068 const LocalVariable& parameter = *scope->VariableAt(num_params - 1); | 3815 const LocalVariable& parameter = *scope->VariableAt(num_params - 1); |
4069 check_pos = parameter.token_pos(); | 3816 check_pos = parameter.token_pos(); |
4070 } | 3817 } |
4071 | 3818 |
4072 if (!check_pos.IsDebugPause()) { | 3819 if (!check_pos.IsDebugPause()) { |
4073 // No parameters or synthetic parameters. | 3820 // No parameters or synthetic parameters. |
4074 check_pos = node->token_pos(); | 3821 check_pos = node->token_pos(); |
4075 ASSERT(check_pos.IsDebugPause()); | 3822 ASSERT(check_pos.IsDebugPause()); |
4076 } | 3823 } |
4077 AddInstruction(new(Z) DebugStepCheckInstr(check_pos, | 3824 AddInstruction( |
4078 RawPcDescriptors::kRuntimeCall)); | 3825 new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall)); |
4079 } | 3826 } |
4080 | 3827 |
4081 // This check may be deleted if the generated code is leaf. | 3828 // This check may be deleted if the generated code is leaf. |
4082 // Native functions don't need a stack check at entry. | 3829 // Native functions don't need a stack check at entry. |
4083 if (is_top_level_sequence && !function.is_native()) { | 3830 if (is_top_level_sequence && !function.is_native()) { |
4084 // Always allocate CheckOverflowInstr so that deopt-ids match regardless | 3831 // Always allocate CheckOverflowInstr so that deopt-ids match regardless |
4085 // if we inline or not. | 3832 // if we inline or not. |
4086 if (!function.IsImplicitGetterFunction() && | 3833 if (!function.IsImplicitGetterFunction() && |
4087 !function.IsImplicitSetterFunction()) { | 3834 !function.IsImplicitSetterFunction()) { |
4088 CheckStackOverflowInstr* check = | 3835 CheckStackOverflowInstr* check = |
4089 new(Z) CheckStackOverflowInstr(node->token_pos(), 0); | 3836 new (Z) CheckStackOverflowInstr(node->token_pos(), 0); |
4090 // If we are inlining don't actually attach the stack check. We must still | 3837 // If we are inlining don't actually attach the stack check. We must still |
4091 // create the stack check in order to allocate a deopt id. | 3838 // create the stack check in order to allocate a deopt id. |
4092 if (!owner()->IsInlining()) { | 3839 if (!owner()->IsInlining()) { |
4093 AddInstruction(check); | 3840 AddInstruction(check); |
4094 } | 3841 } |
4095 } | 3842 } |
4096 } | 3843 } |
4097 | 3844 |
4098 if (Isolate::Current()->type_checks() && is_top_level_sequence) { | 3845 if (Isolate::Current()->type_checks() && is_top_level_sequence) { |
4099 const int num_params = function.NumParameters(); | 3846 const int num_params = function.NumParameters(); |
4100 int pos = 0; | 3847 int pos = 0; |
4101 if (function.IsFactory() || | 3848 if (function.IsFactory() || function.IsDynamicFunction() || |
4102 function.IsDynamicFunction() || | |
4103 function.IsGenerativeConstructor()) { | 3849 function.IsGenerativeConstructor()) { |
4104 // Skip type checking of type arguments for factory functions. | 3850 // Skip type checking of type arguments for factory functions. |
4105 // Skip type checking of receiver for instance functions and constructors. | 3851 // Skip type checking of receiver for instance functions and constructors. |
4106 pos = 1; | 3852 pos = 1; |
4107 } | 3853 } |
4108 while (pos < num_params) { | 3854 while (pos < num_params) { |
4109 const LocalVariable& parameter = *scope->VariableAt(pos); | 3855 const LocalVariable& parameter = *scope->VariableAt(pos); |
4110 ASSERT(parameter.owner() == scope); | 3856 ASSERT(parameter.owner() == scope); |
4111 if (!CanSkipTypeCheck(parameter.token_pos(), | 3857 if (!CanSkipTypeCheck(parameter.token_pos(), NULL, parameter.type(), |
4112 NULL, | |
4113 parameter.type(), | |
4114 parameter.name())) { | 3858 parameter.name())) { |
4115 Value* parameter_value = | 3859 Value* parameter_value = |
4116 Bind(BuildLoadLocal(parameter, parameter.token_pos())); | 3860 Bind(BuildLoadLocal(parameter, parameter.token_pos())); |
4117 Do(BuildAssertAssignable(parameter.token_pos(), | 3861 Do(BuildAssertAssignable(parameter.token_pos(), parameter_value, |
4118 parameter_value, | 3862 parameter.type(), parameter.name())); |
4119 parameter.type(), | |
4120 parameter.name())); | |
4121 } | 3863 } |
4122 pos++; | 3864 pos++; |
4123 } | 3865 } |
4124 } | 3866 } |
4125 | 3867 |
4126 // Continuation part: | 3868 // Continuation part: |
4127 // If this node sequence is the body of a function with continuations, | 3869 // If this node sequence is the body of a function with continuations, |
4128 // leave room for a preamble. | 3870 // leave room for a preamble. |
4129 // The preamble is generated after visiting the body. | 3871 // The preamble is generated after visiting the body. |
4130 GotoInstr* preamble_start = NULL; | 3872 GotoInstr* preamble_start = NULL; |
4131 if (is_top_level_sequence && | 3873 if (is_top_level_sequence && |
4132 (function.IsAsyncClosure() || | 3874 (function.IsAsyncClosure() || function.IsSyncGenClosure() || |
4133 function.IsSyncGenClosure() || | 3875 function.IsAsyncGenClosure())) { |
4134 function.IsAsyncGenClosure())) { | 3876 JoinEntryInstr* preamble_end = new (Z) |
4135 JoinEntryInstr* preamble_end = new(Z) JoinEntryInstr( | 3877 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
4136 owner()->AllocateBlockId(), owner()->try_index()); | |
4137 ASSERT(exit() != NULL); | 3878 ASSERT(exit() != NULL); |
4138 exit()->Goto(preamble_end); | 3879 exit()->Goto(preamble_end); |
4139 ASSERT(exit()->next()->IsGoto()); | 3880 ASSERT(exit()->next()->IsGoto()); |
4140 preamble_start = exit()->next()->AsGoto(); | 3881 preamble_start = exit()->next()->AsGoto(); |
4141 ASSERT(preamble_start->IsGoto()); | 3882 ASSERT(preamble_start->IsGoto()); |
4142 exit_ = preamble_end; | 3883 exit_ = preamble_end; |
4143 } | 3884 } |
4144 | 3885 |
4145 intptr_t i = 0; | 3886 intptr_t i = 0; |
4146 while (is_open() && (i < node->length())) { | 3887 while (is_open() && (i < node->length())) { |
4147 EffectGraphVisitor for_effect(owner()); | 3888 EffectGraphVisitor for_effect(owner()); |
4148 node->NodeAt(i++)->Visit(&for_effect); | 3889 node->NodeAt(i++)->Visit(&for_effect); |
4149 Append(for_effect); | 3890 Append(for_effect); |
4150 if (!is_open()) { | 3891 if (!is_open()) { |
4151 // E.g., because of a JumpNode. | 3892 // E.g., because of a JumpNode. |
4152 break; | 3893 break; |
4153 } | 3894 } |
4154 } | 3895 } |
4155 | 3896 |
4156 // Continuation part: | 3897 // Continuation part: |
4157 // After generating the CFG for the body we can create the preamble | 3898 // After generating the CFG for the body we can create the preamble |
4158 // because we know exactly how many continuation states we need. | 3899 // because we know exactly how many continuation states we need. |
4159 if (is_top_level_sequence && | 3900 if (is_top_level_sequence && |
4160 (function.IsAsyncClosure() || | 3901 (function.IsAsyncClosure() || function.IsSyncGenClosure() || |
4161 function.IsSyncGenClosure() || | 3902 function.IsAsyncGenClosure())) { |
4162 function.IsAsyncGenClosure())) { | |
4163 ASSERT(preamble_start != NULL); | 3903 ASSERT(preamble_start != NULL); |
4164 // We are at the top level. Fetch the corresponding scope. | 3904 // We are at the top level. Fetch the corresponding scope. |
4165 LocalScope* top_scope = node->scope(); | 3905 LocalScope* top_scope = node->scope(); |
4166 LocalVariable* jump_var = top_scope->LookupVariable( | 3906 LocalVariable* jump_var = |
4167 Symbols::AwaitJumpVar(), false); | 3907 top_scope->LookupVariable(Symbols::AwaitJumpVar(), false); |
4168 ASSERT(jump_var != NULL && jump_var->is_captured()); | 3908 ASSERT(jump_var != NULL && jump_var->is_captured()); |
4169 Instruction* saved_entry = entry_; | 3909 Instruction* saved_entry = entry_; |
4170 Instruction* saved_exit = exit_; | 3910 Instruction* saved_exit = exit_; |
4171 entry_ = NULL; | 3911 entry_ = NULL; |
4172 exit_ = NULL; | 3912 exit_ = NULL; |
4173 | 3913 |
4174 LoadLocalNode* load_jump_count = | 3914 LoadLocalNode* load_jump_count = |
4175 new(Z) LoadLocalNode(node->token_pos(), jump_var); | 3915 new (Z) LoadLocalNode(node->token_pos(), jump_var); |
4176 ComparisonNode* check_jump_count; | 3916 ComparisonNode* check_jump_count; |
4177 const intptr_t num_await_states = owner()->await_joins()->length(); | 3917 const intptr_t num_await_states = owner()->await_joins()->length(); |
4178 | 3918 |
4179 LocalVariable* old_context = top_scope->LookupVariable( | 3919 LocalVariable* old_context = |
4180 Symbols::AwaitContextVar(), false); | 3920 top_scope->LookupVariable(Symbols::AwaitContextVar(), false); |
4181 for (intptr_t i = 0; i < num_await_states; i++) { | 3921 for (intptr_t i = 0; i < num_await_states; i++) { |
4182 check_jump_count = new(Z) ComparisonNode( | 3922 check_jump_count = new (Z) |
4183 ST(node->token_pos()), | 3923 ComparisonNode(ST(node->token_pos()), Token::kEQ, load_jump_count, |
4184 Token::kEQ, | 3924 new (Z) LiteralNode(ST(node->token_pos()), |
4185 load_jump_count, | 3925 Smi::ZoneHandle(Z, Smi::New(i)))); |
4186 new(Z) LiteralNode( | |
4187 ST(node->token_pos()), Smi::ZoneHandle(Z, Smi::New(i)))); | |
4188 TestGraphVisitor for_test(owner(), ST(node->token_pos())); | 3926 TestGraphVisitor for_test(owner(), ST(node->token_pos())); |
4189 check_jump_count->Visit(&for_test); | 3927 check_jump_count->Visit(&for_test); |
4190 EffectGraphVisitor for_true(owner()); | 3928 EffectGraphVisitor for_true(owner()); |
4191 EffectGraphVisitor for_false(owner()); | 3929 EffectGraphVisitor for_false(owner()); |
4192 | 3930 |
4193 // Build async jump or sync yield jump. | 3931 // Build async jump or sync yield jump. |
4194 ASSERT(function.IsAsyncClosure() || | 3932 ASSERT(function.IsAsyncClosure() || function.IsAsyncGenClosure() || |
4195 function.IsAsyncGenClosure() || | |
4196 function.IsSyncGenClosure()); | 3933 function.IsSyncGenClosure()); |
4197 | 3934 |
4198 // Restore the saved continuation context, i.e. the context that was | 3935 // Restore the saved continuation context, i.e. the context that was |
4199 // saved into :await_ctx_var before the closure suspended. | 3936 // saved into :await_ctx_var before the closure suspended. |
4200 for_true.BuildRestoreContext(*old_context, ST(node->token_pos())); | 3937 for_true.BuildRestoreContext(*old_context, ST(node->token_pos())); |
4201 | 3938 |
4202 // Goto saved join. | 3939 // Goto saved join. |
4203 for_true.Goto((*owner()->await_joins())[i]); | 3940 for_true.Goto((*owner()->await_joins())[i]); |
4204 | 3941 |
4205 Join(for_test, for_true, for_false); | 3942 Join(for_test, for_true, for_false); |
4206 if (i == 0) { | 3943 if (i == 0) { |
4207 // Manually link up the preamble start. | 3944 // Manually link up the preamble start. |
4208 preamble_start->previous()->set_next(for_test.entry()); | 3945 preamble_start->previous()->set_next(for_test.entry()); |
4209 for_test.entry()->set_previous(preamble_start->previous()); | 3946 for_test.entry()->set_previous(preamble_start->previous()); |
4210 } | 3947 } |
4211 if (i == (num_await_states - 1)) { | 3948 if (i == (num_await_states - 1)) { |
4212 // Link up preamble end. | 3949 // Link up preamble end. |
4213 if (exit_ == NULL) { | 3950 if (exit_ == NULL) { |
4214 exit_ = preamble_start; | 3951 exit_ = preamble_start; |
4215 } else { | 3952 } else { |
4216 exit_->LinkTo(preamble_start); | 3953 exit_->LinkTo(preamble_start); |
4217 } | 3954 } |
4218 } | 3955 } |
4219 } | 3956 } |
4220 entry_ = saved_entry; | 3957 entry_ = saved_entry; |
4221 exit_ = saved_exit; | 3958 exit_ = saved_exit; |
4222 } | 3959 } |
4223 | 3960 |
4224 if (is_open() && | 3961 if (is_open() && (num_context_variables > 0) && |
4225 (num_context_variables > 0) && | |
4226 (!is_top_level_sequence || HasContextScope())) { | 3962 (!is_top_level_sequence || HasContextScope())) { |
4227 UnchainContexts(1); | 3963 UnchainContexts(1); |
4228 } | 3964 } |
4229 | 3965 |
4230 // If this node sequence is labeled, a break out of the sequence will have | 3966 // If this node sequence is labeled, a break out of the sequence will have |
4231 // taken care of unchaining the context. | 3967 // taken care of unchaining the context. |
4232 if (nested_block.break_target() != NULL) { | 3968 if (nested_block.break_target() != NULL) { |
4233 if (is_open()) Goto(nested_block.break_target()); | 3969 if (is_open()) Goto(nested_block.break_target()); |
4234 exit_ = nested_block.break_target(); | 3970 exit_ = nested_block.break_target(); |
4235 } | 3971 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4272 ASSERT(try_handler_index != original_handler_index); | 4008 ASSERT(try_handler_index != original_handler_index); |
4273 owner()->set_try_index(try_handler_index); | 4009 owner()->set_try_index(try_handler_index); |
4274 | 4010 |
4275 // Preserve current context into local variable ':saved_try_context_var'. | 4011 // Preserve current context into local variable ':saved_try_context_var'. |
4276 BuildSaveContext(node->context_var(), ST(node->token_pos())); | 4012 BuildSaveContext(node->context_var(), ST(node->token_pos())); |
4277 | 4013 |
4278 EffectGraphVisitor for_try(owner()); | 4014 EffectGraphVisitor for_try(owner()); |
4279 node->try_block()->Visit(&for_try); | 4015 node->try_block()->Visit(&for_try); |
4280 | 4016 |
4281 if (for_try.is_open()) { | 4017 if (for_try.is_open()) { |
4282 JoinEntryInstr* after_try = | 4018 JoinEntryInstr* after_try = new (Z) |
4283 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 4019 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index); |
4284 original_handler_index); | |
4285 for_try.Goto(after_try); | 4020 for_try.Goto(after_try); |
4286 for_try.exit_ = after_try; | 4021 for_try.exit_ = after_try; |
4287 } | 4022 } |
4288 | 4023 |
4289 JoinEntryInstr* try_entry = | 4024 JoinEntryInstr* try_entry = |
4290 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index); | 4025 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index); |
4291 | 4026 |
4292 Goto(try_entry); | 4027 Goto(try_entry); |
4293 AppendFragment(try_entry, for_try); | 4028 AppendFragment(try_entry, for_try); |
4294 exit_ = for_try.exit_; | 4029 exit_ = for_try.exit_; |
4295 | 4030 |
4296 // We are done generating code for the try block. | 4031 // We are done generating code for the try block. |
4297 owner()->set_try_index(original_handler_index); | 4032 owner()->set_try_index(original_handler_index); |
4298 | 4033 |
4299 // If there is a finally block, it is the handler for code in the catch | 4034 // If there is a finally block, it is the handler for code in the catch |
4300 // block. | 4035 // block. |
4301 const intptr_t catch_handler_index = (finally_block == NULL) | 4036 const intptr_t catch_handler_index = (finally_block == NULL) |
4302 ? original_handler_index | 4037 ? original_handler_index |
4303 : catch_block->catch_handler_index(); | 4038 : catch_block->catch_handler_index(); |
4304 | 4039 |
4305 const intptr_t prev_catch_try_index = owner()->catch_try_index(); | 4040 const intptr_t prev_catch_try_index = owner()->catch_try_index(); |
4306 | 4041 |
4307 owner()->set_try_index(catch_handler_index); | 4042 owner()->set_try_index(catch_handler_index); |
4308 owner()->set_catch_try_index(try_handler_index); | 4043 owner()->set_catch_try_index(try_handler_index); |
4309 EffectGraphVisitor for_catch(owner()); | 4044 EffectGraphVisitor for_catch(owner()); |
4310 catch_block->Visit(&for_catch); | 4045 catch_block->Visit(&for_catch); |
4311 owner()->set_catch_try_index(prev_catch_try_index); | 4046 owner()->set_catch_try_index(prev_catch_try_index); |
4312 | 4047 |
4313 // NOTE: The implicit variables ':saved_try_context_var', ':exception_var' | 4048 // NOTE: The implicit variables ':saved_try_context_var', ':exception_var' |
4314 // and ':stack_trace_var' can never be captured variables. | 4049 // and ':stack_trace_var' can never be captured variables. |
4315 ASSERT(!catch_block->context_var().is_captured()); | 4050 ASSERT(!catch_block->context_var().is_captured()); |
4316 ASSERT(!catch_block->exception_var().is_captured()); | 4051 ASSERT(!catch_block->exception_var().is_captured()); |
4317 ASSERT(!catch_block->stacktrace_var().is_captured()); | 4052 ASSERT(!catch_block->stacktrace_var().is_captured()); |
4318 | 4053 |
4319 CatchBlockEntryInstr* catch_entry = | 4054 CatchBlockEntryInstr* catch_entry = new (Z) CatchBlockEntryInstr( |
4320 new(Z) CatchBlockEntryInstr(owner()->AllocateBlockId(), | 4055 owner()->AllocateBlockId(), catch_handler_index, owner()->graph_entry(), |
4321 catch_handler_index, | 4056 catch_block->handler_types(), try_handler_index, |
4322 owner()->graph_entry(), | 4057 catch_block->exception_var(), catch_block->stacktrace_var(), |
4323 catch_block->handler_types(), | 4058 catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId()); |
4324 try_handler_index, | |
4325 catch_block->exception_var(), | |
4326 catch_block->stacktrace_var(), | |
4327 catch_block->needs_stacktrace(), | |
4328 Thread::Current()->GetNextDeoptId()); | |
4329 owner()->AddCatchEntry(catch_entry); | 4059 owner()->AddCatchEntry(catch_entry); |
4330 AppendFragment(catch_entry, for_catch); | 4060 AppendFragment(catch_entry, for_catch); |
4331 | 4061 |
4332 if (for_catch.is_open()) { | 4062 if (for_catch.is_open()) { |
4333 JoinEntryInstr* join = new(Z) JoinEntryInstr(owner()->AllocateBlockId(), | 4063 JoinEntryInstr* join = new (Z) |
4334 original_handler_index); | 4064 JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index); |
4335 for_catch.Goto(join); | 4065 for_catch.Goto(join); |
4336 if (is_open()) Goto(join); | 4066 if (is_open()) Goto(join); |
4337 exit_ = join; | 4067 exit_ = join; |
4338 } | 4068 } |
4339 | 4069 |
4340 if (finally_block != NULL) { | 4070 if (finally_block != NULL) { |
4341 ASSERT(node->rethrow_clause() != NULL); | 4071 ASSERT(node->rethrow_clause() != NULL); |
4342 // Create a handler for the code in the catch block, containing the | 4072 // Create a handler for the code in the catch block, containing the |
4343 // code in the finally block. | 4073 // code in the finally block. |
4344 owner()->set_try_index(original_handler_index); | 4074 owner()->set_try_index(original_handler_index); |
4345 EffectGraphVisitor for_finally(owner()); | 4075 EffectGraphVisitor for_finally(owner()); |
4346 for_finally.BuildRestoreContext(catch_block->context_var(), | 4076 for_finally.BuildRestoreContext(catch_block->context_var(), |
4347 finally_block->token_pos()); | 4077 finally_block->token_pos()); |
4348 | 4078 |
4349 node->rethrow_clause()->Visit(&for_finally); | 4079 node->rethrow_clause()->Visit(&for_finally); |
4350 if (for_finally.is_open()) { | 4080 if (for_finally.is_open()) { |
4351 // Rethrow the exception. Manually build the graph for rethrow. | 4081 // Rethrow the exception. Manually build the graph for rethrow. |
4352 Value* exception = for_finally.Bind(for_finally.BuildLoadLocal( | 4082 Value* exception = for_finally.Bind(for_finally.BuildLoadLocal( |
4353 catch_block->rethrow_exception_var(), finally_block->token_pos())); | 4083 catch_block->rethrow_exception_var(), finally_block->token_pos())); |
4354 for_finally.PushArgument(exception); | 4084 for_finally.PushArgument(exception); |
4355 Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal( | 4085 Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal( |
4356 catch_block->rethrow_stacktrace_var(), finally_block->token_pos())); | 4086 catch_block->rethrow_stacktrace_var(), finally_block->token_pos())); |
4357 for_finally.PushArgument(stacktrace); | 4087 for_finally.PushArgument(stacktrace); |
4358 for_finally.AddInstruction( | 4088 for_finally.AddInstruction( |
4359 new(Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index)); | 4089 new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index)); |
4360 for_finally.CloseFragment(); | 4090 for_finally.CloseFragment(); |
4361 } | 4091 } |
4362 ASSERT(!for_finally.is_open()); | 4092 ASSERT(!for_finally.is_open()); |
4363 | 4093 |
4364 const Array& types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); | 4094 const Array& types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); |
4365 types.SetAt(0, Object::dynamic_type()); | 4095 types.SetAt(0, Object::dynamic_type()); |
4366 CatchBlockEntryInstr* finally_entry = | 4096 CatchBlockEntryInstr* finally_entry = new (Z) CatchBlockEntryInstr( |
4367 new(Z) CatchBlockEntryInstr(owner()->AllocateBlockId(), | 4097 owner()->AllocateBlockId(), original_handler_index, |
4368 original_handler_index, | 4098 owner()->graph_entry(), types, catch_handler_index, |
4369 owner()->graph_entry(), | 4099 catch_block->exception_var(), catch_block->stacktrace_var(), |
4370 types, | 4100 catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId()); |
4371 catch_handler_index, | |
4372 catch_block->exception_var(), | |
4373 catch_block->stacktrace_var(), | |
4374 catch_block->needs_stacktrace(), | |
4375 Thread::Current()->GetNextDeoptId()); | |
4376 owner()->AddCatchEntry(finally_entry); | 4101 owner()->AddCatchEntry(finally_entry); |
4377 AppendFragment(finally_entry, for_finally); | 4102 AppendFragment(finally_entry, for_finally); |
4378 } | 4103 } |
4379 | 4104 |
4380 // Generate code for the finally block if one exists. | 4105 // Generate code for the finally block if one exists. |
4381 if ((finally_block != NULL) && is_open()) { | 4106 if ((finally_block != NULL) && is_open()) { |
4382 EffectGraphVisitor for_finally_block(owner()); | 4107 EffectGraphVisitor for_finally_block(owner()); |
4383 finally_block->Visit(&for_finally_block); | 4108 finally_block->Visit(&for_finally_block); |
4384 Append(for_finally_block); | 4109 Append(for_finally_block); |
4385 } | 4110 } |
4386 } | 4111 } |
4387 | 4112 |
4388 | 4113 |
4389 // Looks up dynamic method noSuchMethod in target_class | 4114 // Looks up dynamic method noSuchMethod in target_class |
4390 // (including its super class chain) and builds a static call to it. | 4115 // (including its super class chain) and builds a static call to it. |
4391 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( | 4116 StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall( |
4392 const Class& target_class, | 4117 const Class& target_class, |
4393 AstNode* receiver, | 4118 AstNode* receiver, |
4394 const String& method_name, | 4119 const String& method_name, |
4395 ArgumentListNode* method_arguments, | 4120 ArgumentListNode* method_arguments, |
4396 bool save_last_arg, | 4121 bool save_last_arg, |
4397 bool is_super_invocation) { | 4122 bool is_super_invocation) { |
4398 TokenPosition args_pos = method_arguments->token_pos(); | 4123 TokenPosition args_pos = method_arguments->token_pos(); |
4399 LocalVariable* temp = NULL; | 4124 LocalVariable* temp = NULL; |
4400 if (save_last_arg) { | 4125 if (save_last_arg) { |
4401 temp = owner()->parsed_function().expression_temp_var(); | 4126 temp = owner()->parsed_function().expression_temp_var(); |
4402 } | 4127 } |
4403 ArgumentListNode* args = | 4128 ArgumentListNode* args = Parser::BuildNoSuchMethodArguments( |
4404 Parser::BuildNoSuchMethodArguments(args_pos, | 4129 args_pos, method_name, *method_arguments, temp, is_super_invocation); |
4405 method_name, | |
4406 *method_arguments, | |
4407 temp, | |
4408 is_super_invocation); | |
4409 // Make sure we resolve to a compatible noSuchMethod, otherwise call | 4130 // Make sure we resolve to a compatible noSuchMethod, otherwise call |
4410 // noSuchMethod of class Object. | 4131 // noSuchMethod of class Object. |
4411 const int kNumArguments = 2; | 4132 const int kNumArguments = 2; |
4412 ArgumentsDescriptor args_desc( | 4133 ArgumentsDescriptor args_desc( |
4413 Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments))); | 4134 Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments))); |
4414 Function& no_such_method_func = Function::ZoneHandle(Z, | 4135 Function& no_such_method_func = Function::ZoneHandle( |
4415 Resolver::ResolveDynamicForReceiverClass(target_class, | 4136 Z, Resolver::ResolveDynamicForReceiverClass( |
4416 Symbols::NoSuchMethod(), | 4137 target_class, Symbols::NoSuchMethod(), args_desc)); |
4417 args_desc)); | |
4418 if (no_such_method_func.IsNull()) { | 4138 if (no_such_method_func.IsNull()) { |
4419 const Class& object_class = | 4139 const Class& object_class = |
4420 Class::ZoneHandle(Z, isolate()->object_store()->object_class()); | 4140 Class::ZoneHandle(Z, isolate()->object_store()->object_class()); |
4421 no_such_method_func = | 4141 no_such_method_func = Resolver::ResolveDynamicForReceiverClass( |
4422 Resolver::ResolveDynamicForReceiverClass(object_class, | 4142 object_class, Symbols::NoSuchMethod(), args_desc); |
4423 Symbols::NoSuchMethod(), | |
4424 args_desc); | |
4425 } | 4143 } |
4426 // We are guaranteed to find noSuchMethod of class Object. | 4144 // We are guaranteed to find noSuchMethod of class Object. |
4427 ASSERT(!no_such_method_func.IsNull()); | 4145 ASSERT(!no_such_method_func.IsNull()); |
4428 ZoneGrowableArray<PushArgumentInstr*>* push_arguments = | 4146 ZoneGrowableArray<PushArgumentInstr*>* push_arguments = |
4429 new(Z) ZoneGrowableArray<PushArgumentInstr*>(2); | 4147 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); |
4430 BuildPushArguments(*args, push_arguments); | 4148 BuildPushArguments(*args, push_arguments); |
4431 return new(Z) StaticCallInstr(args_pos, | 4149 return new (Z) |
4432 no_such_method_func, | 4150 StaticCallInstr(args_pos, no_such_method_func, Object::null_array(), |
4433 Object::null_array(), | 4151 push_arguments, owner()->ic_data_array()); |
4434 push_arguments, | |
4435 owner()->ic_data_array()); | |
4436 } | 4152 } |
4437 | 4153 |
4438 | 4154 |
4439 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( | 4155 StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError( |
4440 TokenPosition token_pos, | 4156 TokenPosition token_pos, |
4441 const Class& function_class, | 4157 const Class& function_class, |
4442 const String& function_name, | 4158 const String& function_name, |
4443 ArgumentListNode* function_arguments, | 4159 ArgumentListNode* function_arguments, |
4444 int invocation_type) { | 4160 int invocation_type) { |
4445 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 4161 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
4446 new(Z) ZoneGrowableArray<PushArgumentInstr*>(); | 4162 new (Z) ZoneGrowableArray<PushArgumentInstr*>(); |
4447 // Object receiver, actually a class literal of the unresolved method's owner. | 4163 // Object receiver, actually a class literal of the unresolved method's owner. |
4448 AbstractType& type = Type::ZoneHandle( | 4164 AbstractType& type = Type::ZoneHandle( |
4449 Z, | 4165 Z, |
4450 Type::New(function_class, | 4166 Type::New(function_class, TypeArguments::Handle(Z, TypeArguments::null()), |
4451 TypeArguments::Handle(Z, TypeArguments::null()), | 4167 token_pos, Heap::kOld)); |
4452 token_pos, | 4168 type ^= ClassFinalizer::FinalizeType(function_class, type, |
4453 Heap::kOld)); | 4169 ClassFinalizer::kCanonicalize); |
4454 type ^= ClassFinalizer::FinalizeType( | 4170 Value* receiver_value = Bind(new (Z) ConstantInstr(type)); |
4455 function_class, type, ClassFinalizer::kCanonicalize); | |
4456 Value* receiver_value = Bind(new(Z) ConstantInstr(type)); | |
4457 arguments->Add(PushArgument(receiver_value)); | 4171 arguments->Add(PushArgument(receiver_value)); |
4458 // String memberName. | 4172 // String memberName. |
4459 const String& member_name = | 4173 const String& member_name = |
4460 String::ZoneHandle(Z, Symbols::New(T, function_name)); | 4174 String::ZoneHandle(Z, Symbols::New(T, function_name)); |
4461 Value* member_name_value = Bind(new(Z) ConstantInstr(member_name)); | 4175 Value* member_name_value = Bind(new (Z) ConstantInstr(member_name)); |
4462 arguments->Add(PushArgument(member_name_value)); | 4176 arguments->Add(PushArgument(member_name_value)); |
4463 // Smi invocation_type. | 4177 // Smi invocation_type. |
4464 Value* invocation_type_value = Bind(new(Z) ConstantInstr( | 4178 Value* invocation_type_value = Bind( |
4465 Smi::ZoneHandle(Z, Smi::New(invocation_type)))); | 4179 new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(invocation_type)))); |
4466 arguments->Add(PushArgument(invocation_type_value)); | 4180 arguments->Add(PushArgument(invocation_type_value)); |
4467 // List arguments. | 4181 // List arguments. |
4468 if (function_arguments == NULL) { | 4182 if (function_arguments == NULL) { |
4469 Value* arguments_value = Bind( | 4183 Value* arguments_value = |
4470 new(Z) ConstantInstr(Array::ZoneHandle(Z, Array::null()))); | 4184 Bind(new (Z) ConstantInstr(Array::ZoneHandle(Z, Array::null()))); |
4471 arguments->Add(PushArgument(arguments_value)); | 4185 arguments->Add(PushArgument(arguments_value)); |
4472 } else { | 4186 } else { |
4473 ValueGraphVisitor array_val(owner()); | 4187 ValueGraphVisitor array_val(owner()); |
4474 ArrayNode* array = | 4188 ArrayNode* array = |
4475 new(Z) ArrayNode(token_pos, Type::ZoneHandle(Z, Type::ArrayType()), | 4189 new (Z) ArrayNode(token_pos, Type::ZoneHandle(Z, Type::ArrayType()), |
4476 function_arguments->nodes()); | 4190 function_arguments->nodes()); |
4477 array->Visit(&array_val); | 4191 array->Visit(&array_val); |
4478 Append(array_val); | 4192 Append(array_val); |
4479 arguments->Add(PushArgument(array_val.value())); | 4193 arguments->Add(PushArgument(array_val.value())); |
4480 } | 4194 } |
4481 // List argumentNames. | 4195 // List argumentNames. |
4482 ConstantInstr* cinstr = new(Z) ConstantInstr( | 4196 ConstantInstr* cinstr = new (Z) ConstantInstr( |
4483 (function_arguments == NULL) ? Array::ZoneHandle(Z, Array::null()) | 4197 (function_arguments == NULL) ? Array::ZoneHandle(Z, Array::null()) |
4484 : function_arguments->names()); | 4198 : function_arguments->names()); |
4485 Value* argument_names_value = Bind(cinstr); | 4199 Value* argument_names_value = Bind(cinstr); |
4486 arguments->Add(PushArgument(argument_names_value)); | 4200 arguments->Add(PushArgument(argument_names_value)); |
4487 | 4201 |
4488 // List existingArgumentNames. | 4202 // List existingArgumentNames. |
4489 Value* existing_argument_names_value = | 4203 Value* existing_argument_names_value = |
4490 Bind(new(Z) ConstantInstr(Array::ZoneHandle(Z, Array::null()))); | 4204 Bind(new (Z) ConstantInstr(Array::ZoneHandle(Z, Array::null()))); |
4491 arguments->Add(PushArgument(existing_argument_names_value)); | 4205 arguments->Add(PushArgument(existing_argument_names_value)); |
4492 // Resolve and call NoSuchMethodError._throwNew. | 4206 // Resolve and call NoSuchMethodError._throwNew. |
4493 const Library& core_lib = Library::Handle(Z, Library::CoreLibrary()); | 4207 const Library& core_lib = Library::Handle(Z, Library::CoreLibrary()); |
4494 const Class& cls = Class::Handle( | 4208 const Class& cls = |
4495 Z, core_lib.LookupClass(Symbols::NoSuchMethodError())); | 4209 Class::Handle(Z, core_lib.LookupClass(Symbols::NoSuchMethodError())); |
4496 ASSERT(!cls.IsNull()); | 4210 ASSERT(!cls.IsNull()); |
4497 const Function& func = Function::ZoneHandle( | 4211 const Function& func = Function::ZoneHandle( |
4498 Z, | 4212 Z, Resolver::ResolveStatic( |
4499 Resolver::ResolveStatic(cls, | 4213 cls, Library::PrivateCoreLibName(Symbols::ThrowNew()), |
4500 Library::PrivateCoreLibName(Symbols::ThrowNew()), | 4214 arguments->length(), Object::null_array())); |
4501 arguments->length(), | |
4502 Object::null_array())); | |
4503 ASSERT(!func.IsNull()); | 4215 ASSERT(!func.IsNull()); |
4504 return new(Z) StaticCallInstr(token_pos, | 4216 return new (Z) StaticCallInstr(token_pos, func, |
4505 func, | 4217 Object::null_array(), // No names. |
4506 Object::null_array(), // No names. | 4218 arguments, owner()->ic_data_array()); |
4507 arguments, | |
4508 owner()->ic_data_array()); | |
4509 } | 4219 } |
4510 | 4220 |
4511 | 4221 |
4512 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { | 4222 void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) { |
4513 if (FLAG_support_debugger) { | 4223 if (FLAG_support_debugger) { |
4514 if (node->exception()->IsLiteralNode() || | 4224 if (node->exception()->IsLiteralNode() || |
4515 node->exception()->IsLoadLocalNode() || | 4225 node->exception()->IsLoadLocalNode() || |
4516 node->exception()->IsClosureNode()) { | 4226 node->exception()->IsClosureNode()) { |
4517 AddInstruction(new(Z) DebugStepCheckInstr( | 4227 AddInstruction(new (Z) DebugStepCheckInstr( |
4518 node->token_pos(), RawPcDescriptors::kRuntimeCall)); | 4228 node->token_pos(), RawPcDescriptors::kRuntimeCall)); |
4519 } | 4229 } |
4520 } | 4230 } |
4521 ValueGraphVisitor for_exception(owner()); | 4231 ValueGraphVisitor for_exception(owner()); |
4522 node->exception()->Visit(&for_exception); | 4232 node->exception()->Visit(&for_exception); |
4523 Append(for_exception); | 4233 Append(for_exception); |
4524 PushArgument(for_exception.value()); | 4234 PushArgument(for_exception.value()); |
4525 Instruction* instr = NULL; | 4235 Instruction* instr = NULL; |
4526 if (node->stacktrace() == NULL) { | 4236 if (node->stacktrace() == NULL) { |
4527 instr = new(Z) ThrowInstr(node->token_pos()); | 4237 instr = new (Z) ThrowInstr(node->token_pos()); |
4528 } else { | 4238 } else { |
4529 ValueGraphVisitor for_stack_trace(owner()); | 4239 ValueGraphVisitor for_stack_trace(owner()); |
4530 node->stacktrace()->Visit(&for_stack_trace); | 4240 node->stacktrace()->Visit(&for_stack_trace); |
4531 Append(for_stack_trace); | 4241 Append(for_stack_trace); |
4532 PushArgument(for_stack_trace.value()); | 4242 PushArgument(for_stack_trace.value()); |
4533 instr = new(Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index()); | 4243 instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index()); |
4534 } | 4244 } |
4535 AddInstruction(instr); | 4245 AddInstruction(instr); |
4536 } | 4246 } |
4537 | 4247 |
4538 | 4248 |
4539 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { | 4249 void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) { |
4540 BuildThrowNode(node); | 4250 BuildThrowNode(node); |
4541 CloseFragment(); | 4251 CloseFragment(); |
4542 } | 4252 } |
4543 | 4253 |
4544 | 4254 |
4545 // A throw cannot be part of an expression, however, the parser may replace | 4255 // A throw cannot be part of an expression, however, the parser may replace |
4546 // certain expression nodes with a throw. In that case generate a literal null | 4256 // certain expression nodes with a throw. In that case generate a literal null |
4547 // so that the fragment is not closed in the middle of an expression. | 4257 // so that the fragment is not closed in the middle of an expression. |
4548 void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) { | 4258 void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) { |
4549 BuildThrowNode(node); | 4259 BuildThrowNode(node); |
4550 ReturnDefinition(new(Z) ConstantInstr( | 4260 ReturnDefinition( |
4551 Instance::ZoneHandle(Z, Instance::null()))); | 4261 new (Z) ConstantInstr(Instance::ZoneHandle(Z, Instance::null()))); |
4552 } | 4262 } |
4553 | 4263 |
4554 | 4264 |
4555 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 4265 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
4556 InlineBailout("EffectGraphVisitor::VisitInlinedFinallyNode (exception)"); | 4266 InlineBailout("EffectGraphVisitor::VisitInlinedFinallyNode (exception)"); |
4557 const intptr_t try_index = owner()->try_index(); | 4267 const intptr_t try_index = owner()->try_index(); |
4558 if (try_index >= 0) { | 4268 if (try_index >= 0) { |
4559 // We are about to generate code for an inlined finally block. Exceptions | 4269 // We are about to generate code for an inlined finally block. Exceptions |
4560 // thrown in this block of code should be treated as though they are | 4270 // thrown in this block of code should be treated as though they are |
4561 // thrown not from the current try block but the outer try block if any. | 4271 // thrown not from the current try block but the outer try block if any. |
4562 intptr_t outer_try_index = node->try_index(); | 4272 intptr_t outer_try_index = node->try_index(); |
4563 owner()->set_try_index(outer_try_index); | 4273 owner()->set_try_index(outer_try_index); |
4564 } | 4274 } |
4565 | 4275 |
4566 // Note: do not restore the saved_try_context here since the inlined | 4276 // Note: do not restore the saved_try_context here since the inlined |
4567 // code is not reached via an exception handler, therefore the context is | 4277 // code is not reached via an exception handler, therefore the context is |
4568 // always properly set on entry. In other words, the inlined finally clause is | 4278 // always properly set on entry. In other words, the inlined finally clause is |
4569 // never the target of a long jump that would find an uninitialized current | 4279 // never the target of a long jump that would find an uninitialized current |
4570 // context variable. | 4280 // context variable. |
4571 | 4281 |
4572 JoinEntryInstr* finally_entry = | 4282 JoinEntryInstr* finally_entry = |
4573 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 4283 new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
4574 EffectGraphVisitor for_finally_block(owner()); | 4284 EffectGraphVisitor for_finally_block(owner()); |
4575 for_finally_block.AdjustContextLevel(node->finally_block()->scope()); | 4285 for_finally_block.AdjustContextLevel(node->finally_block()->scope()); |
4576 node->finally_block()->Visit(&for_finally_block); | 4286 node->finally_block()->Visit(&for_finally_block); |
4577 | 4287 |
4578 if (try_index >= 0) { | 4288 if (try_index >= 0) { |
4579 owner()->set_try_index(try_index); | 4289 owner()->set_try_index(try_index); |
4580 } | 4290 } |
4581 | 4291 |
4582 if (for_finally_block.is_open()) { | 4292 if (for_finally_block.is_open()) { |
4583 JoinEntryInstr* after_finally = | 4293 JoinEntryInstr* after_finally = new (Z) |
4584 new(Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 4294 JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
4585 for_finally_block.Goto(after_finally); | 4295 for_finally_block.Goto(after_finally); |
4586 for_finally_block.exit_ = after_finally; | 4296 for_finally_block.exit_ = after_finally; |
4587 } | 4297 } |
4588 | 4298 |
4589 Goto(finally_entry); | 4299 Goto(finally_entry); |
4590 AppendFragment(finally_entry, for_finally_block); | 4300 AppendFragment(finally_entry, for_finally_block); |
4591 exit_ = for_finally_block.exit_; | 4301 exit_ = for_finally_block.exit_; |
4592 } | 4302 } |
4593 | 4303 |
4594 | 4304 |
4595 void EffectGraphVisitor::VisitStopNode(StopNode* node) { | 4305 void EffectGraphVisitor::VisitStopNode(StopNode* node) { |
4596 AddInstruction(new(Z) StopInstr(node->message())); | 4306 AddInstruction(new (Z) StopInstr(node->message())); |
4597 } | 4307 } |
4598 | 4308 |
4599 | 4309 |
4600 FlowGraph* FlowGraphBuilder::BuildGraph() { | 4310 FlowGraph* FlowGraphBuilder::BuildGraph() { |
4601 VMTagScope tagScope(thread(), | 4311 VMTagScope tagScope(thread(), VMTag::kCompileFlowGraphBuilderTagId, |
4602 VMTag::kCompileFlowGraphBuilderTagId, | |
4603 FLAG_profile_vm); | 4312 FLAG_profile_vm); |
4604 if (FLAG_support_ast_printer && FLAG_print_ast) { | 4313 if (FLAG_support_ast_printer && FLAG_print_ast) { |
4605 // Print the function ast before IL generation. | 4314 // Print the function ast before IL generation. |
4606 AstPrinter ast_printer; | 4315 AstPrinter ast_printer; |
4607 ast_printer.PrintFunctionNodes(parsed_function()); | 4316 ast_printer.PrintFunctionNodes(parsed_function()); |
4608 } | 4317 } |
4609 if (FLAG_support_ast_printer && FLAG_print_scopes) { | 4318 if (FLAG_support_ast_printer && FLAG_print_scopes) { |
4610 AstPrinter ast_printer; | 4319 AstPrinter ast_printer; |
4611 ast_printer.PrintFunctionScope(parsed_function()); | 4320 ast_printer.PrintFunctionScope(parsed_function()); |
4612 } | 4321 } |
4613 TargetEntryInstr* normal_entry = | 4322 TargetEntryInstr* normal_entry = new (Z) |
4614 new(Z) TargetEntryInstr(AllocateBlockId(), | 4323 TargetEntryInstr(AllocateBlockId(), CatchClauseNode::kInvalidTryIndex); |
4615 CatchClauseNode::kInvalidTryIndex); | |
4616 graph_entry_ = | 4324 graph_entry_ = |
4617 new(Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_); | 4325 new (Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_); |
4618 EffectGraphVisitor for_effect(this); | 4326 EffectGraphVisitor for_effect(this); |
4619 parsed_function().node_sequence()->Visit(&for_effect); | 4327 parsed_function().node_sequence()->Visit(&for_effect); |
4620 AppendFragment(normal_entry, for_effect); | 4328 AppendFragment(normal_entry, for_effect); |
4621 // Check that the graph is properly terminated. | 4329 // Check that the graph is properly terminated. |
4622 ASSERT(!for_effect.is_open()); | 4330 ASSERT(!for_effect.is_open()); |
4623 | 4331 |
4624 // When compiling for OSR, use a depth first search to prune instructions | 4332 // When compiling for OSR, use a depth first search to prune instructions |
4625 // unreachable from the OSR entry. Catch entries are always considered | 4333 // unreachable from the OSR entry. Catch entries are always considered |
4626 // reachable, even if they become unreachable after OSR. | 4334 // reachable, even if they become unreachable after OSR. |
4627 if (osr_id_ != Compiler::kNoOSRDeoptId) { | 4335 if (osr_id_ != Compiler::kNoOSRDeoptId) { |
4628 PruneUnreachable(); | 4336 PruneUnreachable(); |
4629 } | 4337 } |
4630 | 4338 |
4631 FlowGraph* graph = | 4339 FlowGraph* graph = |
4632 new(Z) FlowGraph(parsed_function(), graph_entry_, last_used_block_id_); | 4340 new (Z) FlowGraph(parsed_function(), graph_entry_, last_used_block_id_); |
4633 return graph; | 4341 return graph; |
4634 } | 4342 } |
4635 | 4343 |
4636 | 4344 |
4637 void FlowGraphBuilder::PruneUnreachable() { | 4345 void FlowGraphBuilder::PruneUnreachable() { |
4638 ASSERT(osr_id_ != Compiler::kNoOSRDeoptId); | 4346 ASSERT(osr_id_ != Compiler::kNoOSRDeoptId); |
4639 BitVector* block_marks = new(Z) BitVector(Z, last_used_block_id_ + 1); | 4347 BitVector* block_marks = new (Z) BitVector(Z, last_used_block_id_ + 1); |
4640 bool found = graph_entry_->PruneUnreachable(graph_entry_, NULL, osr_id_, | 4348 bool found = |
4641 block_marks); | 4349 graph_entry_->PruneUnreachable(graph_entry_, NULL, osr_id_, block_marks); |
4642 ASSERT(found); | 4350 ASSERT(found); |
4643 } | 4351 } |
4644 | 4352 |
4645 | 4353 |
4646 void FlowGraphBuilder::Bailout(const char* reason) const { | 4354 void FlowGraphBuilder::Bailout(const char* reason) const { |
4647 parsed_function_.Bailout("FlowGraphBuilder", reason); | 4355 parsed_function_.Bailout("FlowGraphBuilder", reason); |
4648 } | 4356 } |
4649 | 4357 |
4650 } // namespace dart | 4358 } // namespace dart |
OLD | NEW |