OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 // Type of a member function that generates inline code for a native function. | 281 // Type of a member function that generates inline code for a native function. |
282 typedef void (FullCodeGenerator::*InlineFunctionGenerator) | 282 typedef void (FullCodeGenerator::*InlineFunctionGenerator) |
283 (ZoneList<Expression*>*); | 283 (ZoneList<Expression*>*); |
284 | 284 |
285 static const InlineFunctionGenerator kInlineFunctionGenerators[]; | 285 static const InlineFunctionGenerator kInlineFunctionGenerators[]; |
286 | 286 |
287 // A platform-specific utility to overwrite the accumulator register | 287 // A platform-specific utility to overwrite the accumulator register |
288 // with a GC-safe value. | 288 // with a GC-safe value. |
289 void ClearAccumulator(); | 289 void ClearAccumulator(); |
290 | 290 |
291 // Compute the frame pointer relative offset for a given local or | |
292 // parameter slot. | |
293 int SlotOffset(Slot* slot); | |
294 | |
295 // Determine whether or not to inline the smi case for the given | 291 // Determine whether or not to inline the smi case for the given |
296 // operation. | 292 // operation. |
297 bool ShouldInlineSmiCase(Token::Value op); | 293 bool ShouldInlineSmiCase(Token::Value op); |
298 | 294 |
299 // Helper function to convert a pure value into a test context. The value | 295 // Helper function to convert a pure value into a test context. The value |
300 // is expected on the stack or the accumulator, depending on the platform. | 296 // is expected on the stack or the accumulator, depending on the platform. |
301 // See the platform-specific implementation for details. | 297 // See the platform-specific implementation for details. |
302 void DoTest(Expression* condition, | 298 void DoTest(Expression* condition, |
303 Label* if_true, | 299 Label* if_true, |
304 Label* if_false, | 300 Label* if_false, |
305 Label* fall_through); | 301 Label* fall_through); |
306 void DoTest(const TestContext* context); | 302 void DoTest(const TestContext* context); |
307 | 303 |
308 // Helper function to split control flow and avoid a branch to the | 304 // Helper function to split control flow and avoid a branch to the |
309 // fall-through label if it is set up. | 305 // fall-through label if it is set up. |
310 #ifdef V8_TARGET_ARCH_MIPS | 306 #ifdef V8_TARGET_ARCH_MIPS |
311 void Split(Condition cc, | 307 void Split(Condition cc, |
312 Register lhs, | 308 Register lhs, |
313 const Operand& rhs, | 309 const Operand& rhs, |
314 Label* if_true, | 310 Label* if_true, |
315 Label* if_false, | 311 Label* if_false, |
316 Label* fall_through); | 312 Label* fall_through); |
317 #else // All non-mips arch. | 313 #else // All non-mips arch. |
318 void Split(Condition cc, | 314 void Split(Condition cc, |
319 Label* if_true, | 315 Label* if_true, |
320 Label* if_false, | 316 Label* if_false, |
321 Label* fall_through); | 317 Label* fall_through); |
322 #endif // V8_TARGET_ARCH_MIPS | 318 #endif // V8_TARGET_ARCH_MIPS |
323 | 319 |
324 void Move(Slot* dst, Register source, Register scratch1, Register scratch2); | 320 // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into |
325 void Move(Register dst, Slot* source); | 321 // a register. Emits a context chain walk if if necessary (so does |
| 322 // SetVar) so avoid calling both on the same variable. |
| 323 void GetVar(Register destination, Variable* var); |
326 | 324 |
327 // Return an operand used to read/write to a known (ie, non-LOOKUP) slot. | 325 // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable. If it's in |
328 // May emit code to traverse the context chain, destroying the scratch | 326 // the context, the write barrier will be emitted and source, scratch0, |
329 // register. | 327 // scratch1 will be clobbered. Emits a context chain walk if if necessary |
330 MemOperand EmitSlotSearch(Slot* slot, Register scratch); | 328 // (so does GetVar) so avoid calling both on the same variable. |
| 329 void SetVar(Variable* var, |
| 330 Register source, |
| 331 Register scratch0, |
| 332 Register scratch1); |
| 333 |
| 334 // An operand used to read/write a stack-allocated (PARAMETER or LOCAL) |
| 335 // variable. Writing does not need the write barrier. |
| 336 MemOperand StackOperand(Variable* var); |
| 337 |
| 338 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) |
| 339 // variable. May emit code to traverse the context chain, loading the |
| 340 // found context into the scratch register. Writing to this operand will |
| 341 // need the write barrier if location is CONTEXT. |
| 342 MemOperand VarOperand(Variable* var, Register scratch); |
331 | 343 |
332 // Forward the bailout responsibility for the given expression to | 344 // Forward the bailout responsibility for the given expression to |
333 // the next child visited (which must be in a test context). | 345 // the next child visited (which must be in a test context). |
334 void ForwardBailoutToChild(Expression* expr); | 346 void ForwardBailoutToChild(Expression* expr); |
335 | 347 |
336 void VisitForEffect(Expression* expr) { | 348 void VisitForEffect(Expression* expr) { |
337 EffectContext context(this); | 349 EffectContext context(this); |
338 VisitInCurrentContext(expr); | 350 VisitInCurrentContext(expr); |
339 } | 351 } |
340 | 352 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 // should_normalize, the true and false labels are ignored. | 410 // should_normalize, the true and false labels are ignored. |
399 void PrepareForBailoutBeforeSplit(State state, | 411 void PrepareForBailoutBeforeSplit(State state, |
400 bool should_normalize, | 412 bool should_normalize, |
401 Label* if_true, | 413 Label* if_true, |
402 Label* if_false); | 414 Label* if_false); |
403 | 415 |
404 // Platform-specific code for a variable, constant, or function | 416 // Platform-specific code for a variable, constant, or function |
405 // declaration. Functions have an initial value. | 417 // declaration. Functions have an initial value. |
406 void EmitDeclaration(VariableProxy* proxy, | 418 void EmitDeclaration(VariableProxy* proxy, |
407 Variable::Mode mode, | 419 Variable::Mode mode, |
408 FunctionLiteral* function); | 420 FunctionLiteral* function, |
| 421 int* global_count); |
409 | 422 |
410 // Platform-specific code for checking the stack limit at the back edge of | 423 // Platform-specific code for checking the stack limit at the back edge of |
411 // a loop. | 424 // a loop. |
412 void EmitStackCheck(IterationStatement* stmt); | 425 void EmitStackCheck(IterationStatement* stmt); |
413 // Record the OSR AST id corresponding to a stack check in the code. | 426 // Record the OSR AST id corresponding to a stack check in the code. |
414 void RecordStackCheck(int osr_ast_id); | 427 void RecordStackCheck(int osr_ast_id); |
415 // Emit a table of stack check ids and pcs into the code stream. Return | 428 // Emit a table of stack check ids and pcs into the code stream. Return |
416 // the offset of the start of the table. | 429 // the offset of the start of the table. |
417 unsigned EmitStackCheckTable(); | 430 unsigned EmitStackCheckTable(); |
418 | 431 |
(...skipping 10 matching lines...) Expand all Loading... |
429 | 442 |
430 void EmitInlineRuntimeCall(CallRuntime* expr); | 443 void EmitInlineRuntimeCall(CallRuntime* expr); |
431 | 444 |
432 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ | 445 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \ |
433 void Emit##name(ZoneList<Expression*>* arguments); | 446 void Emit##name(ZoneList<Expression*>* arguments); |
434 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 447 INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
435 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) | 448 INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) |
436 #undef EMIT_INLINE_RUNTIME_CALL | 449 #undef EMIT_INLINE_RUNTIME_CALL |
437 | 450 |
438 // Platform-specific code for loading variables. | 451 // Platform-specific code for loading variables. |
439 void EmitLoadGlobalSlotCheckExtensions(Slot* slot, | 452 void EmitLoadGlobalCheckExtensions(Variable* var, |
440 TypeofState typeof_state, | 453 TypeofState typeof_state, |
441 Label* slow); | 454 Label* slow); |
442 MemOperand ContextSlotOperandCheckExtensions(Slot* slot, Label* slow); | 455 MemOperand ContextSlotOperandCheckExtensions(Variable* var, Label* slow); |
443 void EmitDynamicLoadFromSlotFastCase(Slot* slot, | 456 void EmitDynamicLookupFastCase(Variable* var, |
444 TypeofState typeof_state, | 457 TypeofState typeof_state, |
445 Label* slow, | 458 Label* slow, |
446 Label* done); | 459 Label* done); |
447 void EmitVariableLoad(VariableProxy* proxy); | 460 void EmitVariableLoad(VariableProxy* proxy); |
448 | 461 |
449 enum ResolveEvalFlag { | 462 enum ResolveEvalFlag { |
450 SKIP_CONTEXT_LOOKUP, | 463 SKIP_CONTEXT_LOOKUP, |
451 PERFORM_CONTEXT_LOOKUP | 464 PERFORM_CONTEXT_LOOKUP |
452 }; | 465 }; |
453 | 466 |
454 // Expects the arguments and the function already pushed. | 467 // Expects the arguments and the function already pushed. |
455 void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count); | 468 void EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, int arg_count); |
456 | 469 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 codegen()->verify_stack_height(); | 626 codegen()->verify_stack_height(); |
614 } | 627 } |
615 } | 628 } |
616 | 629 |
617 Isolate* isolate() const { return codegen_->isolate(); } | 630 Isolate* isolate() const { return codegen_->isolate(); } |
618 | 631 |
619 // Convert constant control flow (true or false) to the result expected for | 632 // Convert constant control flow (true or false) to the result expected for |
620 // this expression context. | 633 // this expression context. |
621 virtual void Plug(bool flag) const = 0; | 634 virtual void Plug(bool flag) const = 0; |
622 | 635 |
623 // Emit code to convert a pure value (in a register, slot, as a literal, | 636 // Emit code to convert a pure value (in a register, known variable |
624 // or on top of the stack) into the result expected according to this | 637 // location, as a literal, or on top of the stack) into the result |
625 // expression context. | 638 // expected according to this expression context. |
626 virtual void Plug(Register reg) const = 0; | 639 virtual void Plug(Register reg) const = 0; |
627 virtual void Plug(Slot* slot) const = 0; | 640 virtual void Plug(Variable* var) const = 0; |
628 virtual void Plug(Handle<Object> lit) const = 0; | 641 virtual void Plug(Handle<Object> lit) const = 0; |
629 virtual void Plug(Heap::RootListIndex index) const = 0; | 642 virtual void Plug(Heap::RootListIndex index) const = 0; |
630 virtual void PlugTOS() const = 0; | 643 virtual void PlugTOS() const = 0; |
631 | 644 |
632 // Emit code to convert pure control flow to a pair of unbound labels into | 645 // Emit code to convert pure control flow to a pair of unbound labels into |
633 // the result expected according to this expression context. The | 646 // the result expected according to this expression context. The |
634 // implementation will bind both labels unless it's a TestContext, which | 647 // implementation will bind both labels unless it's a TestContext, which |
635 // won't bind them at this point. | 648 // won't bind them at this point. |
636 virtual void Plug(Label* materialize_true, | 649 virtual void Plug(Label* materialize_true, |
637 Label* materialize_false) const = 0; | 650 Label* materialize_false) const = 0; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 class AccumulatorValueContext : public ExpressionContext { | 688 class AccumulatorValueContext : public ExpressionContext { |
676 public: | 689 public: |
677 explicit AccumulatorValueContext(FullCodeGenerator* codegen) | 690 explicit AccumulatorValueContext(FullCodeGenerator* codegen) |
678 : ExpressionContext(codegen) { | 691 : ExpressionContext(codegen) { |
679 expected_stack_height_ = codegen->stack_height(); | 692 expected_stack_height_ = codegen->stack_height(); |
680 } | 693 } |
681 | 694 |
682 virtual void Plug(bool flag) const; | 695 virtual void Plug(bool flag) const; |
683 virtual void Plug(Register reg) const; | 696 virtual void Plug(Register reg) const; |
684 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 697 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
685 virtual void Plug(Slot* slot) const; | 698 virtual void Plug(Variable* var) const; |
686 virtual void Plug(Handle<Object> lit) const; | 699 virtual void Plug(Handle<Object> lit) const; |
687 virtual void Plug(Heap::RootListIndex) const; | 700 virtual void Plug(Heap::RootListIndex) const; |
688 virtual void PlugTOS() const; | 701 virtual void PlugTOS() const; |
689 virtual void DropAndPlug(int count, Register reg) const; | 702 virtual void DropAndPlug(int count, Register reg) const; |
690 virtual void PrepareTest(Label* materialize_true, | 703 virtual void PrepareTest(Label* materialize_true, |
691 Label* materialize_false, | 704 Label* materialize_false, |
692 Label** if_true, | 705 Label** if_true, |
693 Label** if_false, | 706 Label** if_false, |
694 Label** fall_through) const; | 707 Label** fall_through) const; |
695 virtual bool IsAccumulatorValue() const { return true; } | 708 virtual bool IsAccumulatorValue() const { return true; } |
696 }; | 709 }; |
697 | 710 |
698 class StackValueContext : public ExpressionContext { | 711 class StackValueContext : public ExpressionContext { |
699 public: | 712 public: |
700 explicit StackValueContext(FullCodeGenerator* codegen) | 713 explicit StackValueContext(FullCodeGenerator* codegen) |
701 : ExpressionContext(codegen) { | 714 : ExpressionContext(codegen) { |
702 expected_stack_height_ = codegen->stack_height() + 1; | 715 expected_stack_height_ = codegen->stack_height() + 1; |
703 } | 716 } |
704 | 717 |
705 virtual void Plug(bool flag) const; | 718 virtual void Plug(bool flag) const; |
706 virtual void Plug(Register reg) const; | 719 virtual void Plug(Register reg) const; |
707 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 720 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
708 virtual void Plug(Slot* slot) const; | 721 virtual void Plug(Variable* var) const; |
709 virtual void Plug(Handle<Object> lit) const; | 722 virtual void Plug(Handle<Object> lit) const; |
710 virtual void Plug(Heap::RootListIndex) const; | 723 virtual void Plug(Heap::RootListIndex) const; |
711 virtual void PlugTOS() const; | 724 virtual void PlugTOS() const; |
712 virtual void DropAndPlug(int count, Register reg) const; | 725 virtual void DropAndPlug(int count, Register reg) const; |
713 virtual void PrepareTest(Label* materialize_true, | 726 virtual void PrepareTest(Label* materialize_true, |
714 Label* materialize_false, | 727 Label* materialize_false, |
715 Label** if_true, | 728 Label** if_true, |
716 Label** if_false, | 729 Label** if_false, |
717 Label** fall_through) const; | 730 Label** fall_through) const; |
718 virtual bool IsStackValue() const { return true; } | 731 virtual bool IsStackValue() const { return true; } |
(...skipping 20 matching lines...) Expand all Loading... |
739 } | 752 } |
740 | 753 |
741 Expression* condition() const { return condition_; } | 754 Expression* condition() const { return condition_; } |
742 Label* true_label() const { return true_label_; } | 755 Label* true_label() const { return true_label_; } |
743 Label* false_label() const { return false_label_; } | 756 Label* false_label() const { return false_label_; } |
744 Label* fall_through() const { return fall_through_; } | 757 Label* fall_through() const { return fall_through_; } |
745 | 758 |
746 virtual void Plug(bool flag) const; | 759 virtual void Plug(bool flag) const; |
747 virtual void Plug(Register reg) const; | 760 virtual void Plug(Register reg) const; |
748 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 761 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
749 virtual void Plug(Slot* slot) const; | 762 virtual void Plug(Variable* var) const; |
750 virtual void Plug(Handle<Object> lit) const; | 763 virtual void Plug(Handle<Object> lit) const; |
751 virtual void Plug(Heap::RootListIndex) const; | 764 virtual void Plug(Heap::RootListIndex) const; |
752 virtual void PlugTOS() const; | 765 virtual void PlugTOS() const; |
753 virtual void DropAndPlug(int count, Register reg) const; | 766 virtual void DropAndPlug(int count, Register reg) const; |
754 virtual void PrepareTest(Label* materialize_true, | 767 virtual void PrepareTest(Label* materialize_true, |
755 Label* materialize_false, | 768 Label* materialize_false, |
756 Label** if_true, | 769 Label** if_true, |
757 Label** if_false, | 770 Label** if_false, |
758 Label** fall_through) const; | 771 Label** fall_through) const; |
759 virtual bool IsTest() const { return true; } | 772 virtual bool IsTest() const { return true; } |
760 | 773 |
761 private: | 774 private: |
762 Expression* condition_; | 775 Expression* condition_; |
763 Label* true_label_; | 776 Label* true_label_; |
764 Label* false_label_; | 777 Label* false_label_; |
765 Label* fall_through_; | 778 Label* fall_through_; |
766 }; | 779 }; |
767 | 780 |
768 class EffectContext : public ExpressionContext { | 781 class EffectContext : public ExpressionContext { |
769 public: | 782 public: |
770 explicit EffectContext(FullCodeGenerator* codegen) | 783 explicit EffectContext(FullCodeGenerator* codegen) |
771 : ExpressionContext(codegen) { | 784 : ExpressionContext(codegen) { |
772 expected_stack_height_ = codegen->stack_height(); | 785 expected_stack_height_ = codegen->stack_height(); |
773 } | 786 } |
774 | 787 |
775 | 788 |
776 virtual void Plug(bool flag) const; | 789 virtual void Plug(bool flag) const; |
777 virtual void Plug(Register reg) const; | 790 virtual void Plug(Register reg) const; |
778 virtual void Plug(Label* materialize_true, Label* materialize_false) const; | 791 virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
779 virtual void Plug(Slot* slot) const; | 792 virtual void Plug(Variable* var) const; |
780 virtual void Plug(Handle<Object> lit) const; | 793 virtual void Plug(Handle<Object> lit) const; |
781 virtual void Plug(Heap::RootListIndex) const; | 794 virtual void Plug(Heap::RootListIndex) const; |
782 virtual void PlugTOS() const; | 795 virtual void PlugTOS() const; |
783 virtual void DropAndPlug(int count, Register reg) const; | 796 virtual void DropAndPlug(int count, Register reg) const; |
784 virtual void PrepareTest(Label* materialize_true, | 797 virtual void PrepareTest(Label* materialize_true, |
785 Label* materialize_false, | 798 Label* materialize_false, |
786 Label** if_true, | 799 Label** if_true, |
787 Label** if_false, | 800 Label** if_false, |
788 Label** fall_through) const; | 801 Label** fall_through) const; |
789 virtual bool IsEffect() const { return true; } | 802 virtual bool IsEffect() const { return true; } |
(...skipping 14 matching lines...) Expand all Loading... |
804 | 817 |
805 friend class NestedStatement; | 818 friend class NestedStatement; |
806 | 819 |
807 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); | 820 DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); |
808 }; | 821 }; |
809 | 822 |
810 | 823 |
811 } } // namespace v8::internal | 824 } } // namespace v8::internal |
812 | 825 |
813 #endif // V8_FULL_CODEGEN_H_ | 826 #endif // V8_FULL_CODEGEN_H_ |
OLD | NEW |