| 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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 EAGER_ARGUMENTS_ALLOCATION, | 287 EAGER_ARGUMENTS_ALLOCATION, |
| 288 LAZY_ARGUMENTS_ALLOCATION | 288 LAZY_ARGUMENTS_ALLOCATION |
| 289 }; | 289 }; |
| 290 | 290 |
| 291 | 291 |
| 292 // ------------------------------------------------------------------------- | 292 // ------------------------------------------------------------------------- |
| 293 // CodeGenerator | 293 // CodeGenerator |
| 294 | 294 |
| 295 class CodeGenerator: public AstVisitor { | 295 class CodeGenerator: public AstVisitor { |
| 296 public: | 296 public: |
| 297 // Compilation mode. Either the compiler is used as the primary | |
| 298 // compiler and needs to setup everything or the compiler is used as | |
| 299 // the secondary compiler for split compilation and has to handle | |
| 300 // bailouts. | |
| 301 enum Mode { | |
| 302 PRIMARY, | |
| 303 SECONDARY | |
| 304 }; | |
| 305 | |
| 306 // Takes a function literal, generates code for it. This function should only | 297 // Takes a function literal, generates code for it. This function should only |
| 307 // be called by compiler.cc. | 298 // be called by compiler.cc. |
| 308 static Handle<Code> MakeCode(CompilationInfo* info); | 299 static Handle<Code> MakeCode(CompilationInfo* info); |
| 309 | 300 |
| 310 // Printing of AST, etc. as requested by flags. | 301 // Printing of AST, etc. as requested by flags. |
| 311 static void MakeCodePrologue(CompilationInfo* info); | 302 static void MakeCodePrologue(CompilationInfo* info); |
| 312 | 303 |
| 313 // Allocate and install the code. | 304 // Allocate and install the code. |
| 314 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm, | 305 static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm, |
| 315 Code::Flags flags, | 306 Code::Flags flags, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 // reach the end of the statement (ie, it does not exit via break, | 369 // reach the end of the statement (ie, it does not exit via break, |
| 379 // continue, return, or throw). This function is used temporarily while | 370 // continue, return, or throw). This function is used temporarily while |
| 380 // the code generator is being transformed. | 371 // the code generator is being transformed. |
| 381 void VisitAndSpill(Statement* statement); | 372 void VisitAndSpill(Statement* statement); |
| 382 | 373 |
| 383 // Visit a list of statements and then spill the virtual frame if control | 374 // Visit a list of statements and then spill the virtual frame if control |
| 384 // flow can reach the end of the list. | 375 // flow can reach the end of the list. |
| 385 void VisitStatementsAndSpill(ZoneList<Statement*>* statements); | 376 void VisitStatementsAndSpill(ZoneList<Statement*>* statements); |
| 386 | 377 |
| 387 // Main code generation function | 378 // Main code generation function |
| 388 void Generate(CompilationInfo* info, Mode mode); | 379 void Generate(CompilationInfo* info); |
| 389 | 380 |
| 390 // Generate the return sequence code. Should be called no more than | 381 // Generate the return sequence code. Should be called no more than |
| 391 // once per compiled function, immediately after binding the return | 382 // once per compiled function, immediately after binding the return |
| 392 // target (which can not be done more than once). | 383 // target (which can not be done more than once). |
| 393 void GenerateReturnSequence(Result* return_value); | 384 void GenerateReturnSequence(Result* return_value); |
| 394 | 385 |
| 395 // Returns the arguments allocation mode. | 386 // Returns the arguments allocation mode. |
| 396 ArgumentsAllocationMode ArgumentsMode(); | 387 ArgumentsAllocationMode ArgumentsMode(); |
| 397 | 388 |
| 398 // Store the arguments object and allocate it if necessary. | 389 // Store the arguments object and allocate it if necessary. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 OverwriteMode overwrite_mode); | 468 OverwriteMode overwrite_mode); |
| 478 | 469 |
| 479 // Emit code to perform a binary operation on two likely smis. | 470 // Emit code to perform a binary operation on two likely smis. |
| 480 // The code to handle smi arguments is produced inline. | 471 // The code to handle smi arguments is produced inline. |
| 481 // Consumes the Results *left and *right. | 472 // Consumes the Results *left and *right. |
| 482 Result LikelySmiBinaryOperation(Token::Value op, | 473 Result LikelySmiBinaryOperation(Token::Value op, |
| 483 Result* left, | 474 Result* left, |
| 484 Result* right, | 475 Result* right, |
| 485 OverwriteMode overwrite_mode); | 476 OverwriteMode overwrite_mode); |
| 486 | 477 |
| 487 void Comparison(Condition cc, | 478 void Comparison(AstNode* node, |
| 479 Condition cc, |
| 488 bool strict, | 480 bool strict, |
| 489 ControlDestination* destination); | 481 ControlDestination* destination); |
| 490 | 482 |
| 491 // To prevent long attacker-controlled byte sequences, integer constants | 483 // To prevent long attacker-controlled byte sequences, integer constants |
| 492 // from the JavaScript source are loaded in two parts if they are larger | 484 // from the JavaScript source are loaded in two parts if they are larger |
| 493 // than 16 bits. | 485 // than 16 bits. |
| 494 static const int kMaxSmiInlinedBits = 16; | 486 static const int kMaxSmiInlinedBits = 16; |
| 495 bool IsUnsafeSmi(Handle<Object> value); | 487 bool IsUnsafeSmi(Handle<Object> value); |
| 496 // Load an integer constant x into a register target using | 488 // Load an integer constant x into a register target using |
| 497 // at most 16 bits of user-controlled data per assembly operation. | 489 // at most 16 bits of user-controlled data per assembly operation. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 528 // name/value pairs. | 520 // name/value pairs. |
| 529 void DeclareGlobals(Handle<FixedArray> pairs); | 521 void DeclareGlobals(Handle<FixedArray> pairs); |
| 530 | 522 |
| 531 // Instantiate the function boilerplate. | 523 // Instantiate the function boilerplate. |
| 532 void InstantiateBoilerplate(Handle<JSFunction> boilerplate); | 524 void InstantiateBoilerplate(Handle<JSFunction> boilerplate); |
| 533 | 525 |
| 534 // Support for type checks. | 526 // Support for type checks. |
| 535 void GenerateIsSmi(ZoneList<Expression*>* args); | 527 void GenerateIsSmi(ZoneList<Expression*>* args); |
| 536 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); | 528 void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); |
| 537 void GenerateIsArray(ZoneList<Expression*>* args); | 529 void GenerateIsArray(ZoneList<Expression*>* args); |
| 530 void GenerateIsRegExp(ZoneList<Expression*>* args); |
| 538 void GenerateIsObject(ZoneList<Expression*>* args); | 531 void GenerateIsObject(ZoneList<Expression*>* args); |
| 539 void GenerateIsFunction(ZoneList<Expression*>* args); | 532 void GenerateIsFunction(ZoneList<Expression*>* args); |
| 540 void GenerateIsUndetectableObject(ZoneList<Expression*>* args); | 533 void GenerateIsUndetectableObject(ZoneList<Expression*>* args); |
| 541 | 534 |
| 542 // Support for construct call checks. | 535 // Support for construct call checks. |
| 543 void GenerateIsConstructCall(ZoneList<Expression*>* args); | 536 void GenerateIsConstructCall(ZoneList<Expression*>* args); |
| 544 | 537 |
| 545 // Support for arguments.length and arguments[?]. | 538 // Support for arguments.length and arguments[?]. |
| 546 void GenerateArgumentsLength(ZoneList<Expression*>* args); | 539 void GenerateArgumentsLength(ZoneList<Expression*>* args); |
| 547 void GenerateArgumentsAccess(ZoneList<Expression*>* args); | 540 void GenerateArgumentsAccess(ZoneList<Expression*>* args); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 569 | 562 |
| 570 // Fast support for SubString. | 563 // Fast support for SubString. |
| 571 void GenerateSubString(ZoneList<Expression*>* args); | 564 void GenerateSubString(ZoneList<Expression*>* args); |
| 572 | 565 |
| 573 // Fast support for StringCompare. | 566 // Fast support for StringCompare. |
| 574 void GenerateStringCompare(ZoneList<Expression*>* args); | 567 void GenerateStringCompare(ZoneList<Expression*>* args); |
| 575 | 568 |
| 576 // Support for direct calls from JavaScript to native RegExp code. | 569 // Support for direct calls from JavaScript to native RegExp code. |
| 577 void GenerateRegExpExec(ZoneList<Expression*>* args); | 570 void GenerateRegExpExec(ZoneList<Expression*>* args); |
| 578 | 571 |
| 579 // Simple condition analysis. | 572 // Fast support for number to string. |
| 573 void GenerateNumberToString(ZoneList<Expression*>* args); |
| 574 |
| 575 // Fast call to math functions. |
| 576 void GenerateMathSin(ZoneList<Expression*>* args); |
| 577 void GenerateMathCos(ZoneList<Expression*>* args); |
| 578 |
| 579 // Simple condition analysis. |
| 580 enum ConditionAnalysis { | 580 enum ConditionAnalysis { |
| 581 ALWAYS_TRUE, | 581 ALWAYS_TRUE, |
| 582 ALWAYS_FALSE, | 582 ALWAYS_FALSE, |
| 583 DONT_KNOW | 583 DONT_KNOW |
| 584 }; | 584 }; |
| 585 ConditionAnalysis AnalyzeCondition(Expression* cond); | 585 ConditionAnalysis AnalyzeCondition(Expression* cond); |
| 586 | 586 |
| 587 // Methods used to indicate which source code is generated for. Source | 587 // Methods used to indicate which source code is generated for. Source |
| 588 // positions are collected by the assembler and emitted with the relocation | 588 // positions are collected by the assembler and emitted with the relocation |
| 589 // information. | 589 // information. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 enum GenericBinaryFlags { | 647 enum GenericBinaryFlags { |
| 648 NO_GENERIC_BINARY_FLAGS = 0, | 648 NO_GENERIC_BINARY_FLAGS = 0, |
| 649 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub. | 649 NO_SMI_CODE_IN_STUB = 1 << 0 // Omit smi code in stub. |
| 650 }; | 650 }; |
| 651 | 651 |
| 652 | 652 |
| 653 class GenericBinaryOpStub: public CodeStub { | 653 class GenericBinaryOpStub: public CodeStub { |
| 654 public: | 654 public: |
| 655 GenericBinaryOpStub(Token::Value op, | 655 GenericBinaryOpStub(Token::Value op, |
| 656 OverwriteMode mode, | 656 OverwriteMode mode, |
| 657 GenericBinaryFlags flags) | 657 GenericBinaryFlags flags, |
| 658 NumberInfo::Type operands_type = NumberInfo::kUnknown) |
| 658 : op_(op), | 659 : op_(op), |
| 659 mode_(mode), | 660 mode_(mode), |
| 660 flags_(flags), | 661 flags_(flags), |
| 661 args_in_registers_(false), | 662 args_in_registers_(false), |
| 662 args_reversed_(false), | 663 args_reversed_(false), |
| 663 name_(NULL) { | 664 name_(NULL), |
| 665 operands_type_(operands_type) { |
| 664 use_sse3_ = CpuFeatures::IsSupported(SSE3); | 666 use_sse3_ = CpuFeatures::IsSupported(SSE3); |
| 665 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); | 667 ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); |
| 666 } | 668 } |
| 667 | 669 |
| 668 // Generate code to call the stub with the supplied arguments. This will add | 670 // Generate code to call the stub with the supplied arguments. This will add |
| 669 // code at the call site to prepare arguments either in registers or on the | 671 // code at the call site to prepare arguments either in registers or on the |
| 670 // stack together with the actual call. | 672 // stack together with the actual call. |
| 671 void GenerateCall(MacroAssembler* masm, Register left, Register right); | 673 void GenerateCall(MacroAssembler* masm, Register left, Register right); |
| 672 void GenerateCall(MacroAssembler* masm, Register left, Smi* right); | 674 void GenerateCall(MacroAssembler* masm, Register left, Smi* right); |
| 673 void GenerateCall(MacroAssembler* masm, Smi* left, Register right); | 675 void GenerateCall(MacroAssembler* masm, Smi* left, Register right); |
| 674 | 676 |
| 675 Result GenerateCall(MacroAssembler* masm, | 677 Result GenerateCall(MacroAssembler* masm, |
| 676 VirtualFrame* frame, | 678 VirtualFrame* frame, |
| 677 Result* left, | 679 Result* left, |
| 678 Result* right); | 680 Result* right); |
| 679 | 681 |
| 680 private: | 682 private: |
| 681 Token::Value op_; | 683 Token::Value op_; |
| 682 OverwriteMode mode_; | 684 OverwriteMode mode_; |
| 683 GenericBinaryFlags flags_; | 685 GenericBinaryFlags flags_; |
| 684 bool args_in_registers_; // Arguments passed in registers not on the stack. | 686 bool args_in_registers_; // Arguments passed in registers not on the stack. |
| 685 bool args_reversed_; // Left and right argument are swapped. | 687 bool args_reversed_; // Left and right argument are swapped. |
| 686 bool use_sse3_; | 688 bool use_sse3_; |
| 687 char* name_; | 689 char* name_; |
| 690 NumberInfo::Type operands_type_; |
| 688 | 691 |
| 689 const char* GetName(); | 692 const char* GetName(); |
| 690 | 693 |
| 691 #ifdef DEBUG | 694 #ifdef DEBUG |
| 692 void Print() { | 695 void Print() { |
| 693 PrintF("GenericBinaryOpStub (op %s), " | 696 PrintF("GenericBinaryOpStub %d (op %s), " |
| 694 "(mode %d, flags %d, registers %d, reversed %d)\n", | 697 "(mode %d, flags %d, registers %d, reversed %d, only_numbers %s)\n", |
| 698 MinorKey(), |
| 695 Token::String(op_), | 699 Token::String(op_), |
| 696 static_cast<int>(mode_), | 700 static_cast<int>(mode_), |
| 697 static_cast<int>(flags_), | 701 static_cast<int>(flags_), |
| 698 static_cast<int>(args_in_registers_), | 702 static_cast<int>(args_in_registers_), |
| 699 static_cast<int>(args_reversed_)); | 703 static_cast<int>(args_reversed_), |
| 704 NumberInfo::ToString(operands_type_)); |
| 700 } | 705 } |
| 701 #endif | 706 #endif |
| 702 | 707 |
| 703 // Minor key encoding in 16 bits FRASOOOOOOOOOOMM. | 708 // Minor key encoding in 16 bits NNNFRASOOOOOOOMM. |
| 704 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; | 709 class ModeBits: public BitField<OverwriteMode, 0, 2> {}; |
| 705 class OpBits: public BitField<Token::Value, 2, 10> {}; | 710 class OpBits: public BitField<Token::Value, 2, 7> {}; |
| 706 class SSE3Bits: public BitField<bool, 12, 1> {}; | 711 class SSE3Bits: public BitField<bool, 9, 1> {}; |
| 707 class ArgsInRegistersBits: public BitField<bool, 13, 1> {}; | 712 class ArgsInRegistersBits: public BitField<bool, 10, 1> {}; |
| 708 class ArgsReversedBits: public BitField<bool, 14, 1> {}; | 713 class ArgsReversedBits: public BitField<bool, 11, 1> {}; |
| 709 class FlagBits: public BitField<GenericBinaryFlags, 15, 1> {}; | 714 class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {}; |
| 715 class NumberInfoBits: public BitField<NumberInfo::Type, 13, 3> {}; |
| 710 | 716 |
| 711 Major MajorKey() { return GenericBinaryOp; } | 717 Major MajorKey() { return GenericBinaryOp; } |
| 712 int MinorKey() { | 718 int MinorKey() { |
| 713 // Encode the parameters in a unique 16 bit value. | 719 // Encode the parameters in a unique 16 bit value. |
| 714 return OpBits::encode(op_) | 720 return OpBits::encode(op_) |
| 715 | ModeBits::encode(mode_) | 721 | ModeBits::encode(mode_) |
| 716 | FlagBits::encode(flags_) | 722 | FlagBits::encode(flags_) |
| 717 | SSE3Bits::encode(use_sse3_) | 723 | SSE3Bits::encode(use_sse3_) |
| 718 | ArgsInRegistersBits::encode(args_in_registers_) | 724 | ArgsInRegistersBits::encode(args_in_registers_) |
| 719 | ArgsReversedBits::encode(args_reversed_); | 725 | ArgsReversedBits::encode(args_reversed_) |
| 726 | NumberInfoBits::encode(operands_type_); |
| 720 } | 727 } |
| 721 | 728 |
| 722 void Generate(MacroAssembler* masm); | 729 void Generate(MacroAssembler* masm); |
| 723 void GenerateSmiCode(MacroAssembler* masm, Label* slow); | 730 void GenerateSmiCode(MacroAssembler* masm, Label* slow); |
| 724 void GenerateLoadArguments(MacroAssembler* masm); | 731 void GenerateLoadArguments(MacroAssembler* masm); |
| 725 void GenerateReturn(MacroAssembler* masm); | 732 void GenerateReturn(MacroAssembler* masm); |
| 726 | 733 |
| 727 bool ArgsInRegistersSupported() { | 734 bool ArgsInRegistersSupported() { |
| 728 return (op_ == Token::ADD) || (op_ == Token::SUB) | 735 return (op_ == Token::ADD) || (op_ == Token::SUB) |
| 729 || (op_ == Token::MUL) || (op_ == Token::DIV); | 736 || (op_ == Token::MUL) || (op_ == Token::DIV); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 Major MajorKey() { return StringCompare; } | 824 Major MajorKey() { return StringCompare; } |
| 818 int MinorKey() { return 0; } | 825 int MinorKey() { return 0; } |
| 819 | 826 |
| 820 void Generate(MacroAssembler* masm); | 827 void Generate(MacroAssembler* masm); |
| 821 }; | 828 }; |
| 822 | 829 |
| 823 | 830 |
| 824 } } // namespace v8::internal | 831 } } // namespace v8::internal |
| 825 | 832 |
| 826 #endif // V8_X64_CODEGEN_X64_H_ | 833 #endif // V8_X64_CODEGEN_X64_H_ |
| OLD | NEW |