| 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 |