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