OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 DISALLOW_COPY_AND_ASSIGN(HGraph); | 394 DISALLOW_COPY_AND_ASSIGN(HGraph); |
395 }; | 395 }; |
396 | 396 |
397 | 397 |
398 class HEnvironment: public ZoneObject { | 398 class HEnvironment: public ZoneObject { |
399 public: | 399 public: |
400 HEnvironment(HEnvironment* outer, | 400 HEnvironment(HEnvironment* outer, |
401 Scope* scope, | 401 Scope* scope, |
402 Handle<JSFunction> closure); | 402 Handle<JSFunction> closure); |
403 | 403 |
| 404 // Simple accessors. |
| 405 Handle<JSFunction> closure() const { return closure_; } |
| 406 const ZoneList<HValue*>* values() const { return &values_; } |
| 407 const ZoneList<int>* assigned_variables() const { |
| 408 return &assigned_variables_; |
| 409 } |
| 410 int parameter_count() const { return parameter_count_; } |
| 411 int local_count() const { return local_count_; } |
| 412 HEnvironment* outer() const { return outer_; } |
| 413 int pop_count() const { return pop_count_; } |
| 414 int push_count() const { return push_count_; } |
| 415 |
| 416 int ast_id() const { return ast_id_; } |
| 417 void set_ast_id(int id) { ast_id_ = id; } |
| 418 |
| 419 int length() const { return values_.length(); } |
| 420 |
404 void Bind(Variable* variable, HValue* value) { | 421 void Bind(Variable* variable, HValue* value) { |
405 Bind(IndexFor(variable), value); | 422 Bind(IndexFor(variable), value); |
406 | |
407 if (FLAG_trace_environment) { | |
408 PrintF("Slot index=%d name=%s\n", | |
409 variable->AsSlot()->index(), | |
410 *variable->name()->ToCString()); | |
411 } | |
412 } | 423 } |
413 | 424 |
414 void Bind(int index, HValue* value) { | 425 void Bind(int index, HValue* value); |
415 ASSERT(value != NULL); | |
416 if (!assigned_variables_.Contains(index)) { | |
417 assigned_variables_.Add(index); | |
418 } | |
419 values_[index] = value; | |
420 } | |
421 | 426 |
422 HValue* Lookup(Variable* variable) const { | 427 HValue* Lookup(Variable* variable) const { |
423 return Lookup(IndexFor(variable)); | 428 return Lookup(IndexFor(variable)); |
424 } | 429 } |
| 430 |
425 HValue* Lookup(int index) const { | 431 HValue* Lookup(int index) const { |
426 HValue* result = values_[index]; | 432 HValue* result = values_[index]; |
427 ASSERT(result != NULL); | 433 ASSERT(result != NULL); |
428 return result; | 434 return result; |
429 } | 435 } |
430 | 436 |
431 void Push(HValue* value) { | 437 void Push(HValue* value) { |
432 ASSERT(value != NULL); | 438 ASSERT(value != NULL); |
433 ++push_count_; | 439 ++push_count_; |
434 values_.Add(value); | 440 values_.Add(value); |
435 } | 441 } |
436 | 442 |
437 HValue* Top() const { return ExpressionStackAt(0); } | |
438 | |
439 HValue* ExpressionStackAt(int index_from_top) const { | |
440 int index = values_.length() - index_from_top - 1; | |
441 ASSERT(IsExpressionStackIndex(index)); | |
442 return values_[index]; | |
443 } | |
444 | |
445 void SetExpressionStackAt(int index_from_top, HValue* value) { | |
446 int index = values_.length() - index_from_top - 1; | |
447 ASSERT(IsExpressionStackIndex(index)); | |
448 values_[index] = value; | |
449 } | |
450 | |
451 HValue* Pop() { | 443 HValue* Pop() { |
452 ASSERT(!IsExpressionStackEmpty()); | 444 ASSERT(!ExpressionStackIsEmpty()); |
453 if (push_count_ > 0) { | 445 if (push_count_ > 0) { |
454 --push_count_; | 446 --push_count_; |
455 ASSERT(push_count_ >= 0); | |
456 } else { | 447 } else { |
457 ++pop_count_; | 448 ++pop_count_; |
458 } | 449 } |
459 return values_.RemoveLast(); | 450 return values_.RemoveLast(); |
460 } | 451 } |
461 | 452 |
462 void Drop(int count) { | 453 void Drop(int count); |
463 for (int i = 0; i < count; ++i) { | 454 |
464 Pop(); | 455 HValue* Top() const { return ExpressionStackAt(0); } |
465 } | 456 |
| 457 HValue* ExpressionStackAt(int index_from_top) const { |
| 458 int index = length() - index_from_top - 1; |
| 459 ASSERT(HasExpressionAt(index)); |
| 460 return values_[index]; |
466 } | 461 } |
467 | 462 |
468 Handle<JSFunction> closure() const { return closure_; } | 463 void SetExpressionStackAt(int index_from_top, HValue* value); |
469 | 464 |
470 // ID of the original AST node to identify deoptimization points. | |
471 int ast_id() const { return ast_id_; } | |
472 void set_ast_id(int id) { ast_id_ = id; } | |
473 | |
474 const ZoneList<HValue*>* values() const { return &values_; } | |
475 const ZoneList<int>* assigned_variables() const { | |
476 return &assigned_variables_; | |
477 } | |
478 int parameter_count() const { return parameter_count_; } | |
479 int local_count() const { return local_count_; } | |
480 int push_count() const { return push_count_; } | |
481 int pop_count() const { return pop_count_; } | |
482 int total_count() const { return values_.length(); } | |
483 HEnvironment* outer() const { return outer_; } | |
484 HEnvironment* Copy() const; | 465 HEnvironment* Copy() const; |
485 HEnvironment* CopyWithoutHistory() const; | 466 HEnvironment* CopyWithoutHistory() const; |
486 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; | 467 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; |
487 | 468 |
488 // Create an "inlined version" of this environment, where the original | 469 // Create an "inlined version" of this environment, where the original |
489 // environment is the outer environment but the top expression stack | 470 // environment is the outer environment but the top expression stack |
490 // elements are moved to an inner environment as parameters. If | 471 // elements are moved to an inner environment as parameters. If |
491 // is_speculative, the argument values are expected to be PushArgument | 472 // is_speculative, the argument values are expected to be PushArgument |
492 // instructions, otherwise they are the actual values. | 473 // instructions, otherwise they are the actual values. |
493 HEnvironment* CopyForInlining(Handle<JSFunction> target, | 474 HEnvironment* CopyForInlining(Handle<JSFunction> target, |
494 FunctionLiteral* function, | 475 FunctionLiteral* function, |
495 bool is_speculative, | 476 bool is_speculative, |
496 HConstant* undefined) const; | 477 HConstant* undefined) const; |
497 | 478 |
498 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); | 479 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); |
| 480 |
499 void ClearHistory() { | 481 void ClearHistory() { |
500 pop_count_ = 0; | 482 pop_count_ = 0; |
501 push_count_ = 0; | 483 push_count_ = 0; |
502 assigned_variables_.Clear(); | 484 assigned_variables_.Clear(); |
503 } | 485 } |
| 486 |
504 void SetValueAt(int index, HValue* value) { | 487 void SetValueAt(int index, HValue* value) { |
505 ASSERT(index < total_count()); | 488 ASSERT(index < length()); |
506 values_[index] = value; | 489 values_[index] = value; |
507 } | 490 } |
508 | 491 |
509 void PrintTo(StringStream* stream); | 492 void PrintTo(StringStream* stream); |
510 void PrintToStd(); | 493 void PrintToStd(); |
511 | 494 |
512 private: | 495 private: |
513 explicit HEnvironment(const HEnvironment* other); | 496 explicit HEnvironment(const HEnvironment* other); |
514 | 497 |
515 bool IsExpressionStackIndex(int index) const { | 498 // True if index is included in the expression stack part of the environment. |
516 return index >= parameter_count_ + local_count_; | 499 bool HasExpressionAt(int index) const; |
517 } | 500 |
518 bool IsExpressionStackEmpty() const { | 501 bool ExpressionStackIsEmpty() const; |
519 int length = values_.length(); | 502 |
520 int first_expression = parameter_count() + local_count(); | |
521 ASSERT(length >= first_expression); | |
522 return length == first_expression; | |
523 } | |
524 void Initialize(int parameter_count, int local_count, int stack_height); | 503 void Initialize(int parameter_count, int local_count, int stack_height); |
525 void Initialize(const HEnvironment* other); | 504 void Initialize(const HEnvironment* other); |
526 int VariableToIndex(Variable* var); | 505 |
527 int IndexFor(Variable* variable) const; | 506 // Map a variable to an environment index. Parameter indices are shifted |
| 507 // by 1 (receiver is parameter index -1 but environment index 0). |
| 508 // Stack-allocated local indices are shifted by the number of parameters. |
| 509 int IndexFor(Variable* variable) const { |
| 510 Slot* slot = variable->AsSlot(); |
| 511 ASSERT(slot != NULL && slot->IsStackAllocated()); |
| 512 int shift = (slot->type() == Slot::PARAMETER) ? 1 : parameter_count_; |
| 513 return slot->index() + shift; |
| 514 } |
528 | 515 |
529 Handle<JSFunction> closure_; | 516 Handle<JSFunction> closure_; |
530 // Value array [parameters] [locals] [temporaries]. | 517 // Value array [parameters] [locals] [temporaries]. |
531 ZoneList<HValue*> values_; | 518 ZoneList<HValue*> values_; |
532 ZoneList<int> assigned_variables_; | 519 ZoneList<int> assigned_variables_; |
533 int parameter_count_; | 520 int parameter_count_; |
534 int local_count_; | 521 int local_count_; |
535 HEnvironment* outer_; | 522 HEnvironment* outer_; |
536 int pop_count_; | 523 int pop_count_; |
537 int push_count_; | 524 int push_count_; |
(...skipping 22 matching lines...) Expand all Loading... |
560 | 547 |
561 protected: | 548 protected: |
562 AstContext(HGraphBuilder* owner, Expression::Context kind); | 549 AstContext(HGraphBuilder* owner, Expression::Context kind); |
563 virtual ~AstContext(); | 550 virtual ~AstContext(); |
564 | 551 |
565 HGraphBuilder* owner() const { return owner_; } | 552 HGraphBuilder* owner() const { return owner_; } |
566 | 553 |
567 // We want to be able to assert, in a context-specific way, that the stack | 554 // We want to be able to assert, in a context-specific way, that the stack |
568 // height makes sense when the context is filled. | 555 // height makes sense when the context is filled. |
569 #ifdef DEBUG | 556 #ifdef DEBUG |
570 int original_count_; | 557 int original_length_; |
571 #endif | 558 #endif |
572 | 559 |
573 private: | 560 private: |
574 HGraphBuilder* owner_; | 561 HGraphBuilder* owner_; |
575 Expression::Context kind_; | 562 Expression::Context kind_; |
576 AstContext* outer_; | 563 AstContext* outer_; |
577 }; | 564 }; |
578 | 565 |
579 | 566 |
580 class EffectContext: public AstContext { | 567 class EffectContext: public AstContext { |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1061 const char* filename_; | 1048 const char* filename_; |
1062 HeapStringAllocator string_allocator_; | 1049 HeapStringAllocator string_allocator_; |
1063 StringStream trace_; | 1050 StringStream trace_; |
1064 int indent_; | 1051 int indent_; |
1065 }; | 1052 }; |
1066 | 1053 |
1067 | 1054 |
1068 } } // namespace v8::internal | 1055 } } // namespace v8::internal |
1069 | 1056 |
1070 #endif // V8_HYDROGEN_H_ | 1057 #endif // V8_HYDROGEN_H_ |
OLD | NEW |