Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 473 // | 473 // |
| 474 // Label L; // unbound label | 474 // Label L; // unbound label |
| 475 // j(cc, &L); // forward branch to unbound label | 475 // j(cc, &L); // forward branch to unbound label |
| 476 // bind(&L); // bind label to the current pc | 476 // bind(&L); // bind label to the current pc |
| 477 // j(cc, &L); // backward branch to bound label | 477 // j(cc, &L); // backward branch to bound label |
| 478 // bind(&L); // illegal: a label may be bound only once | 478 // bind(&L); // illegal: a label may be bound only once |
| 479 // | 479 // |
| 480 // Note: The same Label can be used for forward and backward branches | 480 // Note: The same Label can be used for forward and backward branches |
| 481 // but it may be bound only once. | 481 // but it may be bound only once. |
| 482 void bind(Label* L); // Binds an unbound label L to current code position. | 482 void bind(Label* L); // Binds an unbound label L to current code position. |
| 483 // Determines if Label is bound and near enough so that branch instruction | |
| 484 // can be used to reach it, instead of jump instruction. | |
| 485 bool is_near(Label* L); | |
| 483 | 486 |
| 484 // Returns the branch offset to the given label from the current code | 487 // Returns the branch offset to the given label from the current code |
| 485 // position. Links the label to the current position if it is still unbound. | 488 // position. Links the label to the current position if it is still unbound. |
| 486 // Manages the jump elimination optimization if the second parameter is true. | 489 // Manages the jump elimination optimization if the second parameter is true. |
| 487 int32_t branch_offset(Label* L, bool jump_elimination_allowed); | 490 int32_t branch_offset(Label* L, bool jump_elimination_allowed); |
| 488 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { | 491 int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) { |
| 489 int32_t o = branch_offset(L, jump_elimination_allowed); | 492 int32_t o = branch_offset(L, jump_elimination_allowed); |
| 490 ASSERT((o & 3) == 0); // Assert the offset is aligned. | 493 ASSERT((o & 3) == 0); // Assert the offset is aligned. |
| 491 return o >> 2; | 494 return o >> 2; |
| 492 } | 495 } |
| 496 uint32_t jump_address(Label* L); | |
| 493 | 497 |
| 494 // Puts a labels target address at the given position. | 498 // Puts a labels target address at the given position. |
| 495 // The high 8 bits are set to zero. | 499 // The high 8 bits are set to zero. |
| 496 void label_at_put(Label* L, int at_offset); | 500 void label_at_put(Label* L, int at_offset); |
| 497 | 501 |
| 498 // Read/Modify the code target address in the branch/call instruction at pc. | 502 // Read/Modify the code target address in the branch/call instruction at pc. |
| 499 static Address target_address_at(Address pc); | 503 static Address target_address_at(Address pc); |
| 500 static void set_target_address_at(Address pc, Address target); | 504 static void set_target_address_at(Address pc, Address target); |
| 501 | 505 |
| 502 // This sets the branch destination (which gets loaded at the call address). | 506 // This sets the branch destination (which gets loaded at the call address). |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 633 | 637 |
| 634 void addiu(Register rd, Register rs, int32_t j); | 638 void addiu(Register rd, Register rs, int32_t j); |
| 635 | 639 |
| 636 // Logical. | 640 // Logical. |
| 637 void and_(Register rd, Register rs, Register rt); | 641 void and_(Register rd, Register rs, Register rt); |
| 638 void or_(Register rd, Register rs, Register rt); | 642 void or_(Register rd, Register rs, Register rt); |
| 639 void xor_(Register rd, Register rs, Register rt); | 643 void xor_(Register rd, Register rs, Register rt); |
| 640 void nor(Register rd, Register rs, Register rt); | 644 void nor(Register rd, Register rs, Register rt); |
| 641 | 645 |
| 642 void andi(Register rd, Register rs, int32_t j); | 646 void andi(Register rd, Register rs, int32_t j); |
| 643 void ori(Register rd, Register rs, int32_t j); | 647 void ori(Register rd, Register rs, int32_t j, bool check_buffer = true); |
|
Søren Thygesen Gjesse
2011/06/24 13:05:15
This boolean flag seems rather obscure - when shou
Paul Lind
2011/06/28 06:53:14
Agree that it was confusing. I have removed the fl
| |
| 644 void xori(Register rd, Register rs, int32_t j); | 648 void xori(Register rd, Register rs, int32_t j); |
| 645 void lui(Register rd, int32_t j); | 649 void lui(Register rd, int32_t j, bool check_buffer = true); |
| 646 | 650 |
| 647 // Shifts. | 651 // Shifts. |
| 648 // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop | 652 // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop |
| 649 // and may cause problems in normal code. coming_from_nop makes sure this | 653 // and may cause problems in normal code. coming_from_nop makes sure this |
| 650 // doesn't happen. | 654 // doesn't happen. |
| 651 void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); | 655 void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false); |
| 652 void sllv(Register rd, Register rt, Register rs); | 656 void sllv(Register rd, Register rt, Register rs); |
| 653 void srl(Register rd, Register rt, uint16_t sa); | 657 void srl(Register rd, Register rt, uint16_t sa); |
| 654 void srlv(Register rd, Register rt, Register rs); | 658 void srlv(Register rd, Register rt, Register rs); |
| 655 void sra(Register rt, Register rd, uint16_t sa); | 659 void sra(Register rt, Register rd, uint16_t sa); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 803 void RecordDebugBreakSlot(); | 807 void RecordDebugBreakSlot(); |
| 804 | 808 |
| 805 // Record the AST id of the CallIC being compiled, so that it can be placed | 809 // Record the AST id of the CallIC being compiled, so that it can be placed |
| 806 // in the relocation information. | 810 // in the relocation information. |
| 807 void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; } | 811 void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; } |
| 808 | 812 |
| 809 // Record a comment relocation entry that can be used by a disassembler. | 813 // Record a comment relocation entry that can be used by a disassembler. |
| 810 // Use --code-comments to enable. | 814 // Use --code-comments to enable. |
| 811 void RecordComment(const char* msg); | 815 void RecordComment(const char* msg); |
| 812 | 816 |
| 817 static void RelocateInternalReference(byte* pc, intptr_t pc_delta); | |
| 818 | |
| 813 // Writes a single byte or word of data in the code stream. Used for | 819 // Writes a single byte or word of data in the code stream. Used for |
| 814 // inline tables, e.g., jump-tables. | 820 // inline tables, e.g., jump-tables. |
| 815 void db(uint8_t data); | 821 void db(uint8_t data); |
| 816 void dd(uint32_t data); | 822 void dd(uint32_t data); |
| 817 | 823 |
| 818 int32_t pc_offset() const { return pc_ - buffer_; } | 824 int32_t pc_offset() const { return pc_ - buffer_; } |
| 819 | 825 |
| 820 PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 826 PositionsRecorder* positions_recorder() { return &positions_recorder_; } |
| 821 | 827 |
| 822 // Postpone the generation of the trampoline pool for the specified number of | 828 // Postpone the generation of the trampoline pool for the specified number of |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 839 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } | 845 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); } |
| 840 void instr_at_put(int pos, Instr instr) { | 846 void instr_at_put(int pos, Instr instr) { |
| 841 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; | 847 *reinterpret_cast<Instr*>(buffer_ + pos) = instr; |
| 842 } | 848 } |
| 843 | 849 |
| 844 // Check if an instruction is a branch of some kind. | 850 // Check if an instruction is a branch of some kind. |
| 845 static bool IsBranch(Instr instr); | 851 static bool IsBranch(Instr instr); |
| 846 static bool IsBeq(Instr instr); | 852 static bool IsBeq(Instr instr); |
| 847 static bool IsBne(Instr instr); | 853 static bool IsBne(Instr instr); |
| 848 | 854 |
| 855 static bool IsJump(Instr instr); | |
| 856 static bool IsJ(Instr instr); | |
| 857 static bool IsLui(Instr instr); | |
| 858 static bool IsOri(Instr instr); | |
| 859 | |
| 849 static bool IsNop(Instr instr, unsigned int type); | 860 static bool IsNop(Instr instr, unsigned int type); |
| 850 static bool IsPop(Instr instr); | 861 static bool IsPop(Instr instr); |
| 851 static bool IsPush(Instr instr); | 862 static bool IsPush(Instr instr); |
| 852 static bool IsLwRegFpOffset(Instr instr); | 863 static bool IsLwRegFpOffset(Instr instr); |
| 853 static bool IsSwRegFpOffset(Instr instr); | 864 static bool IsSwRegFpOffset(Instr instr); |
| 854 static bool IsLwRegFpNegOffset(Instr instr); | 865 static bool IsLwRegFpNegOffset(Instr instr); |
| 855 static bool IsSwRegFpNegOffset(Instr instr); | 866 static bool IsSwRegFpNegOffset(Instr instr); |
| 856 | 867 |
| 857 static Register GetRtReg(Instr instr); | 868 static Register GetRtReg(Instr instr); |
| 858 static Register GetRsReg(Instr instr); | 869 static Register GetRsReg(Instr instr); |
| 859 static Register GetRdReg(Instr instr); | 870 static Register GetRdReg(Instr instr); |
| 860 | 871 |
| 861 static uint32_t GetRt(Instr instr); | 872 static uint32_t GetRt(Instr instr); |
| 862 static uint32_t GetRtField(Instr instr); | 873 static uint32_t GetRtField(Instr instr); |
| 863 static uint32_t GetRs(Instr instr); | 874 static uint32_t GetRs(Instr instr); |
| 864 static uint32_t GetRsField(Instr instr); | 875 static uint32_t GetRsField(Instr instr); |
| 865 static uint32_t GetRd(Instr instr); | 876 static uint32_t GetRd(Instr instr); |
| 866 static uint32_t GetRdField(Instr instr); | 877 static uint32_t GetRdField(Instr instr); |
| 867 static uint32_t GetSa(Instr instr); | 878 static uint32_t GetSa(Instr instr); |
| 868 static uint32_t GetSaField(Instr instr); | 879 static uint32_t GetSaField(Instr instr); |
| 869 static uint32_t GetOpcodeField(Instr instr); | 880 static uint32_t GetOpcodeField(Instr instr); |
| 881 static uint32_t GetFunction(Instr instr); | |
| 882 static uint32_t GetFunctionField(Instr instr); | |
| 870 static uint32_t GetImmediate16(Instr instr); | 883 static uint32_t GetImmediate16(Instr instr); |
| 871 static uint32_t GetLabelConst(Instr instr); | 884 static uint32_t GetLabelConst(Instr instr); |
| 872 | 885 |
| 873 static int32_t GetBranchOffset(Instr instr); | 886 static int32_t GetBranchOffset(Instr instr); |
| 874 static bool IsLw(Instr instr); | 887 static bool IsLw(Instr instr); |
| 875 static int16_t GetLwOffset(Instr instr); | 888 static int16_t GetLwOffset(Instr instr); |
| 876 static Instr SetLwOffset(Instr instr, int16_t offset); | 889 static Instr SetLwOffset(Instr instr, int16_t offset); |
| 877 | 890 |
| 878 static bool IsSw(Instr instr); | 891 static bool IsSw(Instr instr); |
| 879 static Instr SetSwOffset(Instr instr, int16_t offset); | 892 static Instr SetSwOffset(Instr instr, int16_t offset); |
| 880 static bool IsAddImmediate(Instr instr); | 893 static bool IsAddImmediate(Instr instr); |
| 881 static Instr SetAddImmediateOffset(Instr instr, int16_t offset); | 894 static Instr SetAddImmediateOffset(Instr instr, int16_t offset); |
| 882 | 895 |
| 883 static bool IsAndImmediate(Instr instr); | 896 static bool IsAndImmediate(Instr instr); |
| 884 | 897 |
| 885 void CheckTrampolinePool(bool force_emit = false); | 898 void CheckTrampolinePool(); |
| 886 | 899 |
| 887 protected: | 900 protected: |
| 888 // Relocation for a type-recording IC has the AST id added to it. This | 901 // Relocation for a type-recording IC has the AST id added to it. This |
| 889 // member variable is a way to pass the information from the call site to | 902 // member variable is a way to pass the information from the call site to |
| 890 // the relocation info. | 903 // the relocation info. |
| 891 unsigned ast_id_for_reloc_info_; | 904 unsigned ast_id_for_reloc_info_; |
| 892 | 905 |
| 893 bool emit_debug_code() const { return emit_debug_code_; } | 906 bool emit_debug_code() const { return emit_debug_code_; } |
| 894 | 907 |
| 895 int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } | 908 int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 920 } | 933 } |
| 921 | 934 |
| 922 bool is_trampoline_pool_blocked() const { | 935 bool is_trampoline_pool_blocked() const { |
| 923 return trampoline_pool_blocked_nesting_ > 0; | 936 return trampoline_pool_blocked_nesting_ > 0; |
| 924 } | 937 } |
| 925 | 938 |
| 926 bool has_exception() const { | 939 bool has_exception() const { |
| 927 return internal_trampoline_exception_; | 940 return internal_trampoline_exception_; |
| 928 } | 941 } |
| 929 | 942 |
| 943 bool is_trampoline_emitted() const { | |
| 944 return trampoline_emitted_; | |
| 945 } | |
| 946 | |
| 930 private: | 947 private: |
| 931 // Code buffer: | 948 // Code buffer: |
| 932 // The buffer into which code and relocation info are generated. | 949 // The buffer into which code and relocation info are generated. |
| 933 byte* buffer_; | 950 byte* buffer_; |
| 934 int buffer_size_; | 951 int buffer_size_; |
| 935 // True if the assembler owns the buffer, false if buffer is external. | 952 // True if the assembler owns the buffer, false if buffer is external. |
| 936 bool own_buffer_; | 953 bool own_buffer_; |
| 937 | 954 |
| 938 // Buffer size and constant pool distance are checked together at regular | 955 // Buffer size and constant pool distance are checked together at regular |
| 939 // intervals of kBufferCheckInterval emitted bytes. | 956 // intervals of kBufferCheckInterval emitted bytes. |
| 940 static const int kBufferCheckInterval = 1*KB/2; | 957 static const int kBufferCheckInterval = 1*KB/2; |
| 941 | 958 |
| 942 // Code generation. | 959 // Code generation. |
| 943 // The relocation writer's position is at least kGap bytes below the end of | 960 // The relocation writer's position is at least kGap bytes below the end of |
| 944 // the generated instructions. This is so that multi-instruction sequences do | 961 // the generated instructions. This is so that multi-instruction sequences do |
| 945 // not have to check for overflow. The same is true for writes of large | 962 // not have to check for overflow. The same is true for writes of large |
| 946 // relocation info entries. | 963 // relocation info entries. MIPS uses 8 bytes more than other architectures, |
| 947 static const int kGap = 32; | 964 // because it does not check for this gap when instructions with internal |
| 965 // reference relocation info are emitted. | |
| 966 static const int kGap = 40; | |
| 948 byte* pc_; // The program counter - moves forward. | 967 byte* pc_; // The program counter - moves forward. |
| 949 | 968 |
| 950 | 969 |
| 951 // Repeated checking whether the trampoline pool should be emitted is rather | 970 // Repeated checking whether the trampoline pool should be emitted is rather |
| 952 // expensive. By default we only check again once a number of instructions | 971 // expensive. By default we only check again once a number of instructions |
| 953 // has been generated. | 972 // has been generated. |
| 954 static const int kCheckConstIntervalInst = 32; | 973 static const int kCheckConstIntervalInst = 32; |
| 955 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; | 974 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize; |
| 956 | 975 |
| 957 int next_buffer_check_; // pc offset of next buffer check. | 976 int next_buffer_check_; // pc offset of next buffer check. |
| 958 | 977 |
| 959 // Emission of the trampoline pool may be blocked in some code sequences. | 978 // Emission of the trampoline pool may be blocked in some code sequences. |
| 960 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. | 979 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero. |
| 961 int no_trampoline_pool_before_; // Block emission before this pc offset. | 980 int no_trampoline_pool_before_; // Block emission before this pc offset. |
| 962 | 981 |
| 963 // Keep track of the last emitted pool to guarantee a maximal distance. | 982 // Keep track of the last emitted pool to guarantee a maximal distance. |
| 964 int last_trampoline_pool_end_; // pc offset of the end of the last pool. | 983 int last_trampoline_pool_end_; // pc offset of the end of the last pool. |
| 965 | 984 |
| 966 // Relocation information generation. | 985 // Relocation information generation. |
| 967 // Each relocation is encoded as a variable size value. | 986 // Each relocation is encoded as a variable size value. |
| 968 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 987 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; |
| 969 RelocInfoWriter reloc_info_writer; | 988 RelocInfoWriter reloc_info_writer; |
| 970 | 989 |
| 971 // The bound position, before this we cannot do instruction elimination. | 990 // The bound position, before this we cannot do instruction elimination. |
| 972 int last_bound_pos_; | 991 int last_bound_pos_; |
| 973 | 992 |
| 974 // Code emission. | 993 // Code emission. |
| 975 inline void CheckBuffer(); | 994 inline void CheckBuffer(); |
| 976 void GrowBuffer(); | 995 void GrowBuffer(); |
| 977 inline void emit(Instr x); | 996 inline void emit(Instr x, bool check_buffer = true); |
| 978 inline void CheckTrampolinePoolQuick(); | 997 inline void CheckTrampolinePoolQuick(); |
| 979 | 998 |
| 980 // Instruction generation. | 999 // Instruction generation. |
| 981 // We have 3 different kind of encoding layout on MIPS. | 1000 // We have 3 different kind of encoding layout on MIPS. |
| 982 // However due to many different types of objects encoded in the same fields | 1001 // However due to many different types of objects encoded in the same fields |
| 983 // we have quite a few aliases for each mode. | 1002 // we have quite a few aliases for each mode. |
| 984 // Using the same structure to refer to Register and FPURegister would spare a | 1003 // Using the same structure to refer to Register and FPURegister would spare a |
| 985 // few aliases, but mixing both does not look clean to me. | 1004 // few aliases, but mixing both does not look clean to me. |
| 986 // Anyway we could surely implement this differently. | 1005 // Anyway we could surely implement this differently. |
| 987 | 1006 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1016 void GenInstrRegister(Opcode opcode, | 1035 void GenInstrRegister(Opcode opcode, |
| 1017 SecondaryField fmt, | 1036 SecondaryField fmt, |
| 1018 Register rt, | 1037 Register rt, |
| 1019 FPUControlRegister fs, | 1038 FPUControlRegister fs, |
| 1020 SecondaryField func = NULLSF); | 1039 SecondaryField func = NULLSF); |
| 1021 | 1040 |
| 1022 | 1041 |
| 1023 void GenInstrImmediate(Opcode opcode, | 1042 void GenInstrImmediate(Opcode opcode, |
| 1024 Register rs, | 1043 Register rs, |
| 1025 Register rt, | 1044 Register rt, |
| 1026 int32_t j); | 1045 int32_t j, |
| 1046 bool check_buffer = true); | |
| 1027 void GenInstrImmediate(Opcode opcode, | 1047 void GenInstrImmediate(Opcode opcode, |
| 1028 Register rs, | 1048 Register rs, |
| 1029 SecondaryField SF, | 1049 SecondaryField SF, |
| 1030 int32_t j); | 1050 int32_t j); |
| 1031 void GenInstrImmediate(Opcode opcode, | 1051 void GenInstrImmediate(Opcode opcode, |
| 1032 Register r1, | 1052 Register r1, |
| 1033 FPURegister r2, | 1053 FPURegister r2, |
| 1034 int32_t j); | 1054 int32_t j); |
| 1035 | 1055 |
| 1036 | 1056 |
| 1037 void GenInstrJump(Opcode opcode, | 1057 void GenInstrJump(Opcode opcode, |
| 1038 uint32_t address); | 1058 uint32_t address); |
| 1039 | 1059 |
| 1040 // Helpers. | 1060 // Helpers. |
| 1041 void LoadRegPlusOffsetToAt(const MemOperand& src); | 1061 void LoadRegPlusOffsetToAt(const MemOperand& src); |
| 1042 | 1062 |
| 1043 // Labels. | 1063 // Labels. |
| 1044 void print(Label* L); | 1064 void print(Label* L); |
| 1045 void bind_to(Label* L, int pos); | 1065 void bind_to(Label* L, int pos); |
| 1046 void link_to(Label* L, Label* appendix); | |
| 1047 void next(Label* L); | 1066 void next(Label* L); |
| 1048 | 1067 |
| 1049 // One trampoline consists of: | 1068 // One trampoline consists of: |
| 1050 // - space for trampoline slots, | 1069 // - space for trampoline slots, |
| 1051 // - space for labels. | 1070 // - space for labels. |
| 1052 // | 1071 // |
| 1053 // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. | 1072 // Space for trampoline slots is equal to slot_count * 2 * kInstrSize. |
| 1054 // Space for trampoline slots preceeds space for labels. Each label is of one | 1073 // Space for trampoline slots preceeds space for labels. Each label is of one |
| 1055 // instruction size, so total amount for labels is equal to | 1074 // instruction size, so total amount for labels is equal to |
| 1056 // label_count * kInstrSize. | 1075 // label_count * kInstrSize. |
| 1057 class Trampoline { | 1076 class Trampoline { |
| 1058 public: | 1077 public: |
| 1059 Trampoline(int start, int slot_count, int label_count) { | 1078 Trampoline() { |
| 1079 start_ = 0; | |
| 1080 next_slot_ = 0; | |
| 1081 free_slot_count_ = 0; | |
| 1082 end_ = 0; | |
| 1083 } | |
| 1084 Trampoline(int start, int slot_count) { | |
| 1060 start_ = start; | 1085 start_ = start; |
| 1061 next_slot_ = start; | 1086 next_slot_ = start; |
| 1062 free_slot_count_ = slot_count; | 1087 free_slot_count_ = slot_count; |
| 1063 next_label_ = start + slot_count * 2 * kInstrSize; | 1088 end_ = start + slot_count * kTrampolineSlotsSize; |
| 1064 free_label_count_ = label_count; | |
| 1065 end_ = next_label_ + (label_count - 1) * kInstrSize; | |
| 1066 } | 1089 } |
| 1067 int start() { | 1090 int start() { |
| 1068 return start_; | 1091 return start_; |
| 1069 } | 1092 } |
| 1070 int end() { | 1093 int end() { |
| 1071 return end_; | 1094 return end_; |
| 1072 } | 1095 } |
| 1073 int take_slot() { | 1096 int take_slot() { |
| 1074 int trampoline_slot = kInvalidSlotPos; | 1097 int trampoline_slot = kInvalidSlotPos; |
| 1075 if (free_slot_count_ <= 0) { | 1098 if (free_slot_count_ <= 0) { |
| 1076 // We have run out of space on trampolines. | 1099 // We have run out of space on trampolines. |
| 1077 // Make sure we fail in debug mode, so we become aware of each case | 1100 // Make sure we fail in debug mode, so we become aware of each case |
| 1078 // when this happens. | 1101 // when this happens. |
| 1079 ASSERT(0); | 1102 ASSERT(0); |
| 1080 // Internal exception will be caught. | 1103 // Internal exception will be caught. |
| 1081 } else { | 1104 } else { |
| 1082 trampoline_slot = next_slot_; | 1105 trampoline_slot = next_slot_; |
| 1083 free_slot_count_--; | 1106 free_slot_count_--; |
| 1084 next_slot_ += 2*kInstrSize; | 1107 next_slot_ += kTrampolineSlotsSize; |
| 1085 } | 1108 } |
| 1086 return trampoline_slot; | 1109 return trampoline_slot; |
| 1087 } | 1110 } |
| 1088 int take_label() { | |
| 1089 int label_pos = next_label_; | |
| 1090 ASSERT(free_label_count_ > 0); | |
| 1091 free_label_count_--; | |
| 1092 next_label_ += kInstrSize; | |
| 1093 return label_pos; | |
| 1094 } | |
| 1095 | |
| 1096 private: | 1111 private: |
| 1097 int start_; | 1112 int start_; |
| 1098 int end_; | 1113 int end_; |
| 1099 int next_slot_; | 1114 int next_slot_; |
| 1100 int free_slot_count_; | 1115 int free_slot_count_; |
| 1101 int next_label_; | |
| 1102 int free_label_count_; | |
| 1103 }; | 1116 }; |
| 1104 | 1117 |
| 1105 int32_t get_label_entry(int32_t pos, bool next_pool = true); | 1118 int32_t get_trampoline_entry(int32_t pos); |
| 1106 int32_t get_trampoline_entry(int32_t pos, bool next_pool = true); | 1119 int unbound_labels_count; |
| 1107 | 1120 // If trampoline is emitted, generated code is becoming large. As this is |
| 1108 static const int kSlotsPerTrampoline = 2304; | 1121 // already a slow case which can possibly break our code generation for |
|
Søren Thygesen Gjesse
2011/06/24 13:05:15
for -> for the / in the
Paul Lind
2011/06/28 06:53:14
Done.
| |
| 1109 static const int kLabelsPerTrampoline = 8; | 1122 // extreme case, we use this information to trigger different mode for |
|
Søren Thygesen Gjesse
2011/06/24 13:05:15
for -> of
Paul Lind
2011/06/28 06:53:14
Done.
| |
| 1110 static const int kTrampolineInst = | 1123 // branch instruction generation, where we use jump instructions rather |
| 1111 2 * kSlotsPerTrampoline + kLabelsPerTrampoline; | 1124 // than regular branch instructions. |
| 1112 static const int kTrampolineSize = kTrampolineInst * kInstrSize; | 1125 bool trampoline_emitted_; |
| 1126 static const int kTrampolineSlotsSize = 4 * kInstrSize; | |
| 1113 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; | 1127 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; |
| 1114 static const int kMaxDistBetweenPools = | |
| 1115 kMaxBranchOffset - 2 * kTrampolineSize; | |
| 1116 static const int kInvalidSlotPos = -1; | 1128 static const int kInvalidSlotPos = -1; |
| 1117 | 1129 |
| 1118 List<Trampoline> trampolines_; | 1130 Trampoline trampoline_; |
| 1119 bool internal_trampoline_exception_; | 1131 bool internal_trampoline_exception_; |
| 1120 | 1132 |
| 1121 friend class RegExpMacroAssemblerMIPS; | 1133 friend class RegExpMacroAssemblerMIPS; |
| 1122 friend class RelocInfo; | 1134 friend class RelocInfo; |
| 1123 friend class CodePatcher; | 1135 friend class CodePatcher; |
| 1124 friend class BlockTrampolinePoolScope; | 1136 friend class BlockTrampolinePoolScope; |
| 1125 | 1137 |
| 1126 PositionsRecorder positions_recorder_; | 1138 PositionsRecorder positions_recorder_; |
| 1127 bool emit_debug_code_; | 1139 bool emit_debug_code_; |
| 1128 friend class PositionsRecorder; | 1140 friend class PositionsRecorder; |
| 1129 friend class EnsureSpace; | 1141 friend class EnsureSpace; |
| 1130 }; | 1142 }; |
| 1131 | 1143 |
| 1132 | 1144 |
| 1133 class EnsureSpace BASE_EMBEDDED { | 1145 class EnsureSpace BASE_EMBEDDED { |
| 1134 public: | 1146 public: |
| 1135 explicit EnsureSpace(Assembler* assembler) { | 1147 explicit EnsureSpace(Assembler* assembler) { |
| 1136 assembler->CheckBuffer(); | 1148 assembler->CheckBuffer(); |
| 1137 } | 1149 } |
| 1138 }; | 1150 }; |
| 1139 | 1151 |
| 1140 } } // namespace v8::internal | 1152 } } // namespace v8::internal |
| 1141 | 1153 |
| 1142 #endif // V8_ARM_ASSEMBLER_MIPS_H_ | 1154 #endif // V8_ARM_ASSEMBLER_MIPS_H_ |
| OLD | NEW |