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 #ifndef VM_FLOW_GRAPH_BUILDER_H_ | 5 #ifndef VM_FLOW_GRAPH_BUILDER_H_ |
6 #define VM_FLOW_GRAPH_BUILDER_H_ | 6 #define VM_FLOW_GRAPH_BUILDER_H_ |
7 | 7 |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "platform/globals.h" | 9 #include "platform/globals.h" |
10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 | 281 |
282 // Append a 'diamond' branch and join to this graph, depending on which | 282 // Append a 'diamond' branch and join to this graph, depending on which |
283 // parts are reachable. Assumes this graph is open. | 283 // parts are reachable. Assumes this graph is open. |
284 void Join(const TestGraphVisitor& test_fragment, | 284 void Join(const TestGraphVisitor& test_fragment, |
285 const EffectGraphVisitor& true_fragment, | 285 const EffectGraphVisitor& true_fragment, |
286 const EffectGraphVisitor& false_fragment); | 286 const EffectGraphVisitor& false_fragment); |
287 | 287 |
288 // Append a 'while loop' test and back edge to this graph, depending on | 288 // Append a 'while loop' test and back edge to this graph, depending on |
289 // which parts are reachable. Afterward, the graph exit is the false | 289 // which parts are reachable. Afterward, the graph exit is the false |
290 // successor of the loop condition. | 290 // successor of the loop condition. |
291 void TieLoop(intptr_t token_pos, | 291 void TieLoop(TokenPosition token_pos, |
292 const TestGraphVisitor& test_fragment, | 292 const TestGraphVisitor& test_fragment, |
293 const EffectGraphVisitor& body_fragment, | 293 const EffectGraphVisitor& body_fragment, |
294 const EffectGraphVisitor& test_preamble_fragment); | 294 const EffectGraphVisitor& test_preamble_fragment); |
295 | 295 |
296 // Wraps a value in a push-argument instruction and adds the result to the | 296 // Wraps a value in a push-argument instruction and adds the result to the |
297 // graph. | 297 // graph. |
298 PushArgumentInstr* PushArgument(Value* value); | 298 PushArgumentInstr* PushArgument(Value* value); |
299 | 299 |
300 // This implementation shares state among visitors by using the builder. | 300 // This implementation shares state among visitors by using the builder. |
301 // The implementation is incorrect if a visitor that hits a return is not | 301 // The implementation is incorrect if a visitor that hits a return is not |
302 // actually added to the graph. | 302 // actually added to the graph. |
303 void AddReturnExit(intptr_t token_pos, Value* value); | 303 void AddReturnExit(TokenPosition token_pos, Value* value); |
304 | 304 |
305 protected: | 305 protected: |
306 Definition* BuildStoreTemp(const LocalVariable& local, | 306 Definition* BuildStoreTemp(const LocalVariable& local, |
307 Value* value, | 307 Value* value, |
308 intptr_t token_pos); | 308 TokenPosition token_pos); |
309 Definition* BuildStoreExprTemp(Value* value, intptr_t token_pos); | 309 Definition* BuildStoreExprTemp(Value* value, TokenPosition token_pos); |
310 Definition* BuildLoadExprTemp(intptr_t token_pos); | 310 Definition* BuildLoadExprTemp(TokenPosition token_pos); |
311 | 311 |
312 Definition* BuildStoreLocal(const LocalVariable& local, | 312 Definition* BuildStoreLocal(const LocalVariable& local, |
313 Value* value, | 313 Value* value, |
314 intptr_t token_pos); | 314 TokenPosition token_pos); |
315 Definition* BuildLoadLocal(const LocalVariable& local, | 315 Definition* BuildLoadLocal(const LocalVariable& local, |
316 intptr_t token_pos); | 316 TokenPosition token_pos); |
317 LoadLocalInstr* BuildLoadThisVar(LocalScope* scope, intptr_t token_pos); | 317 LoadLocalInstr* BuildLoadThisVar(LocalScope* scope, |
| 318 TokenPosition token_pos); |
318 LoadFieldInstr* BuildNativeGetter( | 319 LoadFieldInstr* BuildNativeGetter( |
319 NativeBodyNode* node, | 320 NativeBodyNode* node, |
320 MethodRecognizer::Kind kind, | 321 MethodRecognizer::Kind kind, |
321 intptr_t offset, | 322 intptr_t offset, |
322 const Type& type, | 323 const Type& type, |
323 intptr_t class_id); | 324 intptr_t class_id); |
324 // Assumes setter parameter is named 'value'. Returns null constant. | 325 // Assumes setter parameter is named 'value'. Returns null constant. |
325 ConstantInstr* DoNativeSetterStoreValue( | 326 ConstantInstr* DoNativeSetterStoreValue( |
326 NativeBodyNode* node, | 327 NativeBodyNode* node, |
327 intptr_t offset, | 328 intptr_t offset, |
328 StoreBarrierType emit_store_barrier); | 329 StoreBarrierType emit_store_barrier); |
329 | 330 |
330 // Helpers for translating parts of the AST. | 331 // Helpers for translating parts of the AST. |
331 void BuildPushArguments(const ArgumentListNode& node, | 332 void BuildPushArguments(const ArgumentListNode& node, |
332 ZoneGrowableArray<PushArgumentInstr*>* values); | 333 ZoneGrowableArray<PushArgumentInstr*>* values); |
333 | 334 |
334 // Creates an instantiated type argument vector used in preparation of an | 335 // Creates an instantiated type argument vector used in preparation of an |
335 // allocation call. | 336 // allocation call. |
336 // May be called only if allocating an object of a parameterized class. | 337 // May be called only if allocating an object of a parameterized class. |
337 Value* BuildInstantiatedTypeArguments( | 338 Value* BuildInstantiatedTypeArguments( |
338 intptr_t token_pos, | 339 TokenPosition token_pos, |
339 const TypeArguments& type_arguments); | 340 const TypeArguments& type_arguments); |
340 | 341 |
341 void BuildTypecheckPushArguments( | 342 void BuildTypecheckPushArguments( |
342 intptr_t token_pos, | 343 TokenPosition token_pos, |
343 PushArgumentInstr** push_instantiator_type_arguments); | 344 PushArgumentInstr** push_instantiator_type_arguments); |
344 void BuildTypecheckArguments(intptr_t token_pos, | 345 void BuildTypecheckArguments(TokenPosition token_pos, |
345 Value** instantiator_type_arguments); | 346 Value** instantiator_type_arguments); |
346 Value* BuildInstantiator(intptr_t token_pos); | 347 Value* BuildInstantiator(TokenPosition token_pos); |
347 Value* BuildInstantiatorTypeArguments(intptr_t token_pos, | 348 Value* BuildInstantiatorTypeArguments(TokenPosition token_pos, |
348 const Class& instantiator_class, | 349 const Class& instantiator_class, |
349 Value* instantiator); | 350 Value* instantiator); |
350 | 351 |
351 // Perform a type check on the given value. | 352 // Perform a type check on the given value. |
352 AssertAssignableInstr* BuildAssertAssignable(intptr_t token_pos, | 353 AssertAssignableInstr* BuildAssertAssignable(TokenPosition token_pos, |
353 Value* value, | 354 Value* value, |
354 const AbstractType& dst_type, | 355 const AbstractType& dst_type, |
355 const String& dst_name); | 356 const String& dst_name); |
356 | 357 |
357 // Perform a type check on the given value and return it. | 358 // Perform a type check on the given value and return it. |
358 Value* BuildAssignableValue(intptr_t token_pos, | 359 Value* BuildAssignableValue(TokenPosition token_pos, |
359 Value* value, | 360 Value* value, |
360 const AbstractType& dst_type, | 361 const AbstractType& dst_type, |
361 const String& dst_name); | 362 const String& dst_name); |
362 | 363 |
363 static const bool kResultNeeded = true; | 364 static const bool kResultNeeded = true; |
364 static const bool kResultNotNeeded = false; | 365 static const bool kResultNotNeeded = false; |
365 | 366 |
366 Definition* BuildStoreIndexedValues(StoreIndexedNode* node, | 367 Definition* BuildStoreIndexedValues(StoreIndexedNode* node, |
367 bool result_is_needed); | 368 bool result_is_needed); |
368 | 369 |
369 void BuildInstanceSetterArguments( | 370 void BuildInstanceSetterArguments( |
370 InstanceSetterNode* node, | 371 InstanceSetterNode* node, |
371 ZoneGrowableArray<PushArgumentInstr*>* arguments, | 372 ZoneGrowableArray<PushArgumentInstr*>* arguments, |
372 bool result_is_needed); | 373 bool result_is_needed); |
373 | 374 |
374 StrictCompareInstr* BuildStrictCompare(AstNode* left, | 375 StrictCompareInstr* BuildStrictCompare(AstNode* left, |
375 AstNode* right, | 376 AstNode* right, |
376 Token::Kind kind, | 377 Token::Kind kind, |
377 intptr_t token_pos); | 378 TokenPosition token_pos); |
378 | 379 |
379 virtual void BuildTypeTest(ComparisonNode* node); | 380 virtual void BuildTypeTest(ComparisonNode* node); |
380 virtual void BuildTypeCast(ComparisonNode* node); | 381 virtual void BuildTypeCast(ComparisonNode* node); |
381 | 382 |
382 bool HasContextScope() const; | 383 bool HasContextScope() const; |
383 | 384 |
384 // Moves the nth parent context into the context register. | 385 // Moves the nth parent context into the context register. |
385 void UnchainContexts(intptr_t n); | 386 void UnchainContexts(intptr_t n); |
386 | 387 |
387 // Unchain the current context until its level matches the context level | 388 // Unchain the current context until its level matches the context level |
388 // expected on entry at the target specified by its scope. | 389 // expected on entry at the target specified by its scope. |
389 void AdjustContextLevel(LocalScope* target_scope); | 390 void AdjustContextLevel(LocalScope* target_scope); |
390 | 391 |
391 void CloseFragment() { exit_ = NULL; } | 392 void CloseFragment() { exit_ = NULL; } |
392 | 393 |
393 // Returns a local variable index for a temporary local that is | 394 // Returns a local variable index for a temporary local that is |
394 // on top of the current expression stack. | 395 // on top of the current expression stack. |
395 intptr_t GetCurrentTempLocalIndex() const; | 396 intptr_t GetCurrentTempLocalIndex() const; |
396 | 397 |
397 Value* BuildObjectAllocation(ConstructorCallNode* node); | 398 Value* BuildObjectAllocation(ConstructorCallNode* node); |
398 void BuildConstructorCall(ConstructorCallNode* node, | 399 void BuildConstructorCall(ConstructorCallNode* node, |
399 PushArgumentInstr* alloc_value); | 400 PushArgumentInstr* alloc_value); |
400 | 401 |
401 void BuildSaveContext(const LocalVariable& variable, | 402 void BuildSaveContext(const LocalVariable& variable, |
402 intptr_t token_pos); | 403 TokenPosition token_pos); |
403 void BuildRestoreContext(const LocalVariable& variable, | 404 void BuildRestoreContext(const LocalVariable& variable, |
404 intptr_t token_pos); | 405 TokenPosition token_pos); |
405 | 406 |
406 Definition* BuildStoreContext(Value* value, intptr_t token_pos); | 407 Definition* BuildStoreContext(Value* value, TokenPosition token_pos); |
407 Definition* BuildCurrentContext(intptr_t token_pos); | 408 Definition* BuildCurrentContext(TokenPosition token_pos); |
408 | 409 |
409 void BuildThrowNode(ThrowNode* node); | 410 void BuildThrowNode(ThrowNode* node); |
410 | 411 |
411 StaticCallInstr* BuildStaticNoSuchMethodCall( | 412 StaticCallInstr* BuildStaticNoSuchMethodCall( |
412 const Class& target_class, | 413 const Class& target_class, |
413 AstNode* receiver, | 414 AstNode* receiver, |
414 const String& method_name, | 415 const String& method_name, |
415 ArgumentListNode* method_arguments, | 416 ArgumentListNode* method_arguments, |
416 bool save_last_arg, | 417 bool save_last_arg, |
417 bool is_super_invocation); | 418 bool is_super_invocation); |
418 | 419 |
419 StaticCallInstr* BuildThrowNoSuchMethodError( | 420 StaticCallInstr* BuildThrowNoSuchMethodError( |
420 intptr_t token_pos, | 421 TokenPosition token_pos, |
421 const Class& function_class, | 422 const Class& function_class, |
422 const String& function_name, | 423 const String& function_name, |
423 ArgumentListNode* function_arguments, | 424 ArgumentListNode* function_arguments, |
424 int invocation_type); | 425 int invocation_type); |
425 | 426 |
426 void BuildStaticSetter(StaticSetterNode* node, bool result_is_needed); | 427 void BuildStaticSetter(StaticSetterNode* node, bool result_is_needed); |
427 Definition* BuildStoreStaticField(StoreStaticFieldNode* node, | 428 Definition* BuildStoreStaticField(StoreStaticFieldNode* node, |
428 bool result_is_needed, | 429 bool result_is_needed, |
429 intptr_t token_pos); | 430 TokenPosition token_pos); |
430 | 431 |
431 void BuildClosureCall(ClosureCallNode* node, bool result_needed); | 432 void BuildClosureCall(ClosureCallNode* node, bool result_needed); |
432 | 433 |
433 Value* BuildNullValue(intptr_t token_pos); | 434 Value* BuildNullValue(TokenPosition token_pos); |
434 | 435 |
435 // Returns true if the run-time type check can be eliminated. | 436 // Returns true if the run-time type check can be eliminated. |
436 bool CanSkipTypeCheck(intptr_t token_pos, | 437 bool CanSkipTypeCheck(TokenPosition token_pos, |
437 Value* value, | 438 Value* value, |
438 const AbstractType& dst_type, | 439 const AbstractType& dst_type, |
439 const String& dst_name); | 440 const String& dst_name); |
440 | 441 |
441 // Helpers for allocating and deallocating temporary locals on top of the | 442 // Helpers for allocating and deallocating temporary locals on top of the |
442 // expression stack. | 443 // expression stack. |
443 LocalVariable* EnterTempLocalScope(Value* value, intptr_t token_pos); | 444 LocalVariable* EnterTempLocalScope(Value* value, TokenPosition token_pos); |
444 Definition* ExitTempLocalScope(LocalVariable* var, intptr_t token_pos); | 445 Definition* ExitTempLocalScope(LocalVariable* var, TokenPosition token_pos); |
445 | 446 |
446 void BuildLetTempExpressions(LetNode* node); | 447 void BuildLetTempExpressions(LetNode* node); |
447 | 448 |
448 void BuildInstanceGetterConditional(InstanceGetterNode* node); | 449 void BuildInstanceGetterConditional(InstanceGetterNode* node); |
449 void BuildInstanceCallConditional(InstanceCallNode* node); | 450 void BuildInstanceCallConditional(InstanceCallNode* node); |
450 | 451 |
451 Thread* thread() const { return owner()->thread(); } | 452 Thread* thread() const { return owner()->thread(); } |
452 Isolate* isolate() const { return owner()->isolate(); } | 453 Isolate* isolate() const { return owner()->isolate(); } |
453 Zone* zone() const { return owner()->zone(); } | 454 Zone* zone() const { return owner()->zone(); } |
454 | 455 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 // - Neither NULL: true and false successors at the given addresses | 539 // - Neither NULL: true and false successors at the given addresses |
539 // | 540 // |
540 // We expect that AstNode in test contexts either have only nonlocal exits | 541 // We expect that AstNode in test contexts either have only nonlocal exits |
541 // or else control flow has both true and false successors. | 542 // or else control flow has both true and false successors. |
542 // | 543 // |
543 // The cis and token_pos are used in checked mode to verify that the | 544 // The cis and token_pos are used in checked mode to verify that the |
544 // condition of the test is of type bool. | 545 // condition of the test is of type bool. |
545 class TestGraphVisitor : public ValueGraphVisitor { | 546 class TestGraphVisitor : public ValueGraphVisitor { |
546 public: | 547 public: |
547 TestGraphVisitor(FlowGraphBuilder* owner, | 548 TestGraphVisitor(FlowGraphBuilder* owner, |
548 intptr_t condition_token_pos) | 549 TokenPosition condition_token_pos) |
549 : ValueGraphVisitor(owner), | 550 : ValueGraphVisitor(owner), |
550 true_successor_addresses_(1), | 551 true_successor_addresses_(1), |
551 false_successor_addresses_(1), | 552 false_successor_addresses_(1), |
552 condition_token_pos_(condition_token_pos) { } | 553 condition_token_pos_(condition_token_pos) { } |
553 | 554 |
554 void IfFalseGoto(JoinEntryInstr* join) const; | 555 void IfFalseGoto(JoinEntryInstr* join) const; |
555 void IfTrueGoto(JoinEntryInstr* join) const; | 556 void IfTrueGoto(JoinEntryInstr* join) const; |
556 | 557 |
557 BlockEntryInstr* CreateTrueSuccessor() const; | 558 BlockEntryInstr* CreateTrueSuccessor() const; |
558 BlockEntryInstr* CreateFalseSuccessor() const; | 559 BlockEntryInstr* CreateFalseSuccessor() const; |
559 | 560 |
560 virtual void VisitBinaryOpNode(BinaryOpNode* node); | 561 virtual void VisitBinaryOpNode(BinaryOpNode* node); |
561 | 562 |
562 intptr_t condition_token_pos() const { return condition_token_pos_; } | 563 TokenPosition condition_token_pos() const { return condition_token_pos_; } |
563 | 564 |
564 private: | 565 private: |
565 // Construct and concatenate a Branch instruction to this graph fragment. | 566 // Construct and concatenate a Branch instruction to this graph fragment. |
566 // Closes the fragment and sets the output parameters. | 567 // Closes the fragment and sets the output parameters. |
567 virtual void ReturnValue(Value* value); | 568 virtual void ReturnValue(Value* value); |
568 | 569 |
569 // Either merges the definition into a BranchInstr (Comparison, BooleanNegate) | 570 // Either merges the definition into a BranchInstr (Comparison, BooleanNegate) |
570 // or adds the definition to the graph and returns a use of its value. | 571 // or adds the definition to the graph and returns a use of its value. |
571 virtual void ReturnDefinition(Definition* definition); | 572 virtual void ReturnDefinition(Definition* definition); |
572 | 573 |
573 void MergeBranchWithComparison(ComparisonInstr* comp); | 574 void MergeBranchWithComparison(ComparisonInstr* comp); |
574 void MergeBranchWithNegate(BooleanNegateInstr* comp); | 575 void MergeBranchWithNegate(BooleanNegateInstr* comp); |
575 | 576 |
576 BlockEntryInstr* CreateSuccessorFor( | 577 BlockEntryInstr* CreateSuccessorFor( |
577 const GrowableArray<TargetEntryInstr**>& branches) const; | 578 const GrowableArray<TargetEntryInstr**>& branches) const; |
578 | 579 |
579 void ConnectBranchesTo( | 580 void ConnectBranchesTo( |
580 const GrowableArray<TargetEntryInstr**>& branches, | 581 const GrowableArray<TargetEntryInstr**>& branches, |
581 JoinEntryInstr* join) const; | 582 JoinEntryInstr* join) const; |
582 | 583 |
583 // Output parameters. | 584 // Output parameters. |
584 GrowableArray<TargetEntryInstr**> true_successor_addresses_; | 585 GrowableArray<TargetEntryInstr**> true_successor_addresses_; |
585 GrowableArray<TargetEntryInstr**> false_successor_addresses_; | 586 GrowableArray<TargetEntryInstr**> false_successor_addresses_; |
586 | 587 |
587 intptr_t condition_token_pos_; | 588 TokenPosition condition_token_pos_; |
588 }; | 589 }; |
589 | 590 |
590 } // namespace dart | 591 } // namespace dart |
591 | 592 |
592 #endif // VM_FLOW_GRAPH_BUILDER_H_ | 593 #endif // VM_FLOW_GRAPH_BUILDER_H_ |
OLD | NEW |