| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 | 90 |
| 91 // Emit all kMaterializeObject instructions describing objects to be | 91 // Emit all kMaterializeObject instructions describing objects to be |
| 92 // materialized on the deoptimization as a prefix to the deoptimization info. | 92 // materialized on the deoptimization as a prefix to the deoptimization info. |
| 93 EmitMaterializations(deopt_env_, builder); | 93 EmitMaterializations(deopt_env_, builder); |
| 94 | 94 |
| 95 // The real frame starts here. | 95 // The real frame starts here. |
| 96 builder->MarkFrameStart(); | 96 builder->MarkFrameStart(); |
| 97 | 97 |
| 98 Zone* zone = compiler->zone(); | 98 Zone* zone = compiler->zone(); |
| 99 | 99 |
| 100 // Current PP, FP, and PC. | |
| 101 builder->AddPp(current->function(), slot_ix++); | 100 builder->AddPp(current->function(), slot_ix++); |
| 102 builder->AddPcMarker(Function::Handle(zone), slot_ix++); | 101 builder->AddPcMarker(Function::Handle(zone), slot_ix++); |
| 103 builder->AddCallerFp(slot_ix++); | 102 builder->AddCallerFp(slot_ix++); |
| 104 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); | 103 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); |
| 105 | 104 |
| 106 // Emit all values that are needed for materialization as a part of the | 105 // Emit all values that are needed for materialization as a part of the |
| 107 // expression stack for the bottom-most frame. This guarantees that GC | 106 // expression stack for the bottom-most frame. This guarantees that GC |
| 108 // will be able to find them during materialization. | 107 // will be able to find them during materialization. |
| 109 slot_ix = builder->EmitMaterializationArguments(slot_ix); | 108 slot_ix = builder->EmitMaterializationArguments(slot_ix); |
| 110 | 109 |
| 111 // For the innermost environment, set outgoing arguments and the locals. | 110 // For the innermost environment, set outgoing arguments and the locals. |
| 112 for (intptr_t i = current->Length() - 1; | 111 for (intptr_t i = current->Length() - 1; |
| 113 i >= current->fixed_parameter_count(); | 112 i >= current->fixed_parameter_count(); |
| 114 i--) { | 113 i--) { |
| 115 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); | 114 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); |
| 116 } | 115 } |
| 117 | 116 |
| 118 Environment* previous = current; | 117 Environment* previous = current; |
| 119 current = current->outer(); | 118 current = current->outer(); |
| 120 while (current != NULL) { | 119 while (current != NULL) { |
| 121 // PP, FP, and PC. | |
| 122 builder->AddPp(current->function(), slot_ix++); | 120 builder->AddPp(current->function(), slot_ix++); |
| 123 builder->AddPcMarker(previous->function(), slot_ix++); | 121 builder->AddPcMarker(previous->function(), slot_ix++); |
| 124 builder->AddCallerFp(slot_ix++); | 122 builder->AddCallerFp(slot_ix++); |
| 125 | 123 |
| 126 // For any outer environment the deopt id is that of the call instruction | 124 // For any outer environment the deopt id is that of the call instruction |
| 127 // which is recorded in the outer environment. | 125 // which is recorded in the outer environment. |
| 128 builder->AddReturnAddress( | 126 builder->AddReturnAddress( |
| 129 current->function(), | 127 current->function(), |
| 130 Isolate::ToDeoptAfter(current->deopt_id()), | 128 Isolate::ToDeoptAfter(current->deopt_id()), |
| 131 slot_ix++); | 129 slot_ix++); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 147 slot_ix++); | 145 slot_ix++); |
| 148 } | 146 } |
| 149 | 147 |
| 150 // Iterate on the outer environment. | 148 // Iterate on the outer environment. |
| 151 previous = current; | 149 previous = current; |
| 152 current = current->outer(); | 150 current = current->outer(); |
| 153 } | 151 } |
| 154 // The previous pointer is now the outermost environment. | 152 // The previous pointer is now the outermost environment. |
| 155 ASSERT(previous != NULL); | 153 ASSERT(previous != NULL); |
| 156 | 154 |
| 157 // For the outermost environment, set caller PC, caller PP, and caller FP. | 155 // Add slots for the outermost environment. |
| 158 builder->AddCallerPp(slot_ix++); | 156 builder->AddCallerPp(slot_ix++); |
| 159 // PC marker. | |
| 160 builder->AddPcMarker(previous->function(), slot_ix++); | 157 builder->AddPcMarker(previous->function(), slot_ix++); |
| 161 builder->AddCallerFp(slot_ix++); | 158 builder->AddCallerFp(slot_ix++); |
| 162 builder->AddCallerPc(slot_ix++); | 159 builder->AddCallerPc(slot_ix++); |
| 163 | 160 |
| 164 // For the outermost environment, set the incoming arguments. | 161 // For the outermost environment, set the incoming arguments. |
| 165 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { | 162 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
| 166 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); | 163 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); |
| 167 } | 164 } |
| 168 | 165 |
| 169 return builder->CreateDeoptInfo(deopt_table); | 166 return builder->CreateDeoptInfo(deopt_table); |
| 170 } | 167 } |
| 171 | 168 |
| 172 | 169 |
| 173 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 170 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
| 174 intptr_t stub_ix) { | 171 intptr_t stub_ix) { |
| 175 // Calls do not need stubs, they share a deoptimization trampoline. | 172 // Calls do not need stubs, they share a deoptimization trampoline. |
| 176 ASSERT(reason() != ICData::kDeoptAtCall); | 173 ASSERT(reason() != ICData::kDeoptAtCall); |
| 177 Assembler* assem = compiler->assembler(); | 174 Assembler* assem = compiler->assembler(); |
| 178 #define __ assem-> | 175 #define __ assem-> |
| 179 __ Comment("%s", Name()); | 176 __ Comment("%s", Name()); |
| 180 __ Bind(entry_label()); | 177 __ Bind(entry_label()); |
| 181 if (FLAG_trap_on_deoptimization) { | 178 if (FLAG_trap_on_deoptimization) { |
| 182 __ brk(0); | 179 __ brk(0); |
| 183 } | 180 } |
| 184 | 181 |
| 185 ASSERT(deopt_env() != NULL); | 182 ASSERT(deopt_env() != NULL); |
| 186 | 183 __ Push(CODE_REG); |
| 187 __ BranchLink(*StubCode::Deoptimize_entry()); | 184 __ BranchLink(*StubCode::Deoptimize_entry()); |
| 188 set_pc_offset(assem->CodeSize()); | 185 set_pc_offset(assem->CodeSize()); |
| 189 #undef __ | 186 #undef __ |
| 190 } | 187 } |
| 191 | 188 |
| 192 | 189 |
| 193 #define __ assembler()-> | 190 #define __ assembler()-> |
| 194 | 191 |
| 195 | 192 |
| 196 // Fall through if bool_register contains null. | 193 // Fall through if bool_register contains null. |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); | 901 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); |
| 905 __ SmiUntag(R7); | 902 __ SmiUntag(R7); |
| 906 // Check that R8 equals R7, i.e. no named arguments passed. | 903 // Check that R8 equals R7, i.e. no named arguments passed. |
| 907 __ CompareRegisters(R8, R7); | 904 __ CompareRegisters(R8, R7); |
| 908 __ b(&all_arguments_processed, EQ); | 905 __ b(&all_arguments_processed, EQ); |
| 909 } | 906 } |
| 910 } | 907 } |
| 911 | 908 |
| 912 __ Bind(&wrong_num_arguments); | 909 __ Bind(&wrong_num_arguments); |
| 913 if (function.IsClosureFunction()) { | 910 if (function.IsClosureFunction()) { |
| 914 ASSERT(assembler()->constant_pool_allowed()); | 911 __ LeaveDartFrame(kKeepCalleePP); // The arguments are still on the stack. |
| 915 __ LeaveDartFrame(); // The arguments are still on the stack. | |
| 916 // Do not use caller's pool ptr in branch. | |
| 917 ASSERT(!assembler()->constant_pool_allowed()); | |
| 918 __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry()); | 912 __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry()); |
| 919 __ set_constant_pool_allowed(true); | |
| 920 // The noSuchMethod call may return to the caller, but not here. | 913 // The noSuchMethod call may return to the caller, but not here. |
| 921 } else if (check_correct_named_args) { | 914 } else if (check_correct_named_args) { |
| 922 __ Stop("Wrong arguments"); | 915 __ Stop("Wrong arguments"); |
| 923 } | 916 } |
| 924 | 917 |
| 925 __ Bind(&all_arguments_processed); | 918 __ Bind(&all_arguments_processed); |
| 926 // Nullify originally passed arguments only after they have been copied and | 919 // Nullify originally passed arguments only after they have been copied and |
| 927 // checked, otherwise noSuchMethod would not see their original values. | 920 // checked, otherwise noSuchMethod would not see their original values. |
| 928 // This step can be skipped in case we decide that formal parameters are | 921 // This step can be skipped in case we decide that formal parameters are |
| 929 // implicitly final, since garbage collecting the unmodified value is not | 922 // implicitly final, since garbage collecting the unmodified value is not |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 (!is_optimizing() || may_reoptimize())) { | 971 (!is_optimizing() || may_reoptimize())) { |
| 979 const Register function_reg = R6; | 972 const Register function_reg = R6; |
| 980 new_pp = R13; | 973 new_pp = R13; |
| 981 // The pool pointer is not setup before entering the Dart frame. | 974 // The pool pointer is not setup before entering the Dart frame. |
| 982 // Temporarily setup pool pointer for this dart function. | 975 // Temporarily setup pool pointer for this dart function. |
| 983 __ LoadPoolPointer(new_pp); | 976 __ LoadPoolPointer(new_pp); |
| 984 | 977 |
| 985 // Load function object using the callee's pool pointer. | 978 // Load function object using the callee's pool pointer. |
| 986 __ LoadFunctionFromCalleePool(function_reg, function, new_pp); | 979 __ LoadFunctionFromCalleePool(function_reg, function, new_pp); |
| 987 | 980 |
| 988 // Patch point is after the eventually inlined function object. | |
| 989 entry_patch_pc_offset_ = assembler()->CodeSize(); | |
| 990 | |
| 991 __ LoadFieldFromOffset( | 981 __ LoadFieldFromOffset( |
| 992 R7, function_reg, Function::usage_counter_offset(), kWord); | 982 R7, function_reg, Function::usage_counter_offset(), kWord); |
| 993 // Reoptimization of an optimized function is triggered by counting in | 983 // Reoptimization of an optimized function is triggered by counting in |
| 994 // IC stubs, but not at the entry of the function. | 984 // IC stubs, but not at the entry of the function. |
| 995 if (!is_optimizing()) { | 985 if (!is_optimizing()) { |
| 996 __ add(R7, R7, Operand(1)); | 986 __ add(R7, R7, Operand(1)); |
| 997 __ StoreFieldToOffset( | 987 __ StoreFieldToOffset( |
| 998 R7, function_reg, Function::usage_counter_offset(), kWord); | 988 R7, function_reg, Function::usage_counter_offset(), kWord); |
| 999 } | 989 } |
| 1000 __ CompareImmediate(R7, GetOptimizationThreshold()); | 990 __ CompareImmediate(R7, GetOptimizationThreshold()); |
| 1001 ASSERT(function_reg == R6); | 991 ASSERT(function_reg == R6); |
| 1002 Label dont_optimize; | 992 Label dont_optimize; |
| 1003 __ b(&dont_optimize, LT); | 993 __ b(&dont_optimize, LT); |
| 1004 __ Branch(*StubCode::OptimizeFunction_entry()); | 994 __ Branch(*StubCode::OptimizeFunction_entry(), new_pp); |
| 1005 __ Bind(&dont_optimize); | 995 __ Bind(&dont_optimize); |
| 1006 } else if (!flow_graph().IsCompiledForOsr()) { | |
| 1007 entry_patch_pc_offset_ = assembler()->CodeSize(); | |
| 1008 } | 996 } |
| 1009 __ Comment("Enter frame"); | 997 __ Comment("Enter frame"); |
| 1010 if (flow_graph().IsCompiledForOsr()) { | 998 if (flow_graph().IsCompiledForOsr()) { |
| 1011 intptr_t extra_slots = StackSize() | 999 intptr_t extra_slots = StackSize() |
| 1012 - flow_graph().num_stack_locals() | 1000 - flow_graph().num_stack_locals() |
| 1013 - flow_graph().num_copied_params(); | 1001 - flow_graph().num_copied_params(); |
| 1014 ASSERT(extra_slots >= 0); | 1002 ASSERT(extra_slots >= 0); |
| 1015 __ EnterOsrFrame(extra_slots * kWordSize, new_pp); | 1003 __ EnterOsrFrame(extra_slots * kWordSize, new_pp); |
| 1016 } else { | 1004 } else { |
| 1017 ASSERT(StackSize() >= 0); | 1005 ASSERT(StackSize() >= 0); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 Label correct_num_arguments, wrong_num_arguments; | 1047 Label correct_num_arguments, wrong_num_arguments; |
| 1060 __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset()); | 1048 __ LoadFieldFromOffset(R0, R4, ArgumentsDescriptor::count_offset()); |
| 1061 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); | 1049 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); |
| 1062 __ b(&wrong_num_arguments, NE); | 1050 __ b(&wrong_num_arguments, NE); |
| 1063 __ LoadFieldFromOffset(R1, R4, | 1051 __ LoadFieldFromOffset(R1, R4, |
| 1064 ArgumentsDescriptor::positional_count_offset()); | 1052 ArgumentsDescriptor::positional_count_offset()); |
| 1065 __ CompareRegisters(R0, R1); | 1053 __ CompareRegisters(R0, R1); |
| 1066 __ b(&correct_num_arguments, EQ); | 1054 __ b(&correct_num_arguments, EQ); |
| 1067 __ Bind(&wrong_num_arguments); | 1055 __ Bind(&wrong_num_arguments); |
| 1068 if (function.IsClosureFunction()) { | 1056 if (function.IsClosureFunction()) { |
| 1069 ASSERT(assembler()->constant_pool_allowed()); | 1057 __ LeaveDartFrame(kKeepCalleePP); // Arguments are still on the stack. |
| 1070 __ LeaveDartFrame(); // The arguments are still on the stack. | |
| 1071 // Do not use caller's pool ptr in branch. | |
| 1072 ASSERT(!assembler()->constant_pool_allowed()); | |
| 1073 __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry()); | 1058 __ BranchPatchable(*StubCode::CallClosureNoSuchMethod_entry()); |
| 1074 __ set_constant_pool_allowed(true); | |
| 1075 // The noSuchMethod call may return to the caller, but not here. | 1059 // The noSuchMethod call may return to the caller, but not here. |
| 1076 } else { | 1060 } else { |
| 1077 __ Stop("Wrong number of arguments"); | 1061 __ Stop("Wrong number of arguments"); |
| 1078 } | 1062 } |
| 1079 __ Bind(&correct_num_arguments); | 1063 __ Bind(&correct_num_arguments); |
| 1080 } | 1064 } |
| 1081 } else if (!flow_graph().IsCompiledForOsr()) { | 1065 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1082 CopyParameters(); | 1066 CopyParameters(); |
| 1083 } | 1067 } |
| 1084 | 1068 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1118 } | 1102 } |
| 1119 } | 1103 } |
| 1120 } | 1104 } |
| 1121 | 1105 |
| 1122 VisitBlocks(); | 1106 VisitBlocks(); |
| 1123 | 1107 |
| 1124 __ brk(0); | 1108 __ brk(0); |
| 1125 ASSERT(assembler()->constant_pool_allowed()); | 1109 ASSERT(assembler()->constant_pool_allowed()); |
| 1126 GenerateDeferredCode(); | 1110 GenerateDeferredCode(); |
| 1127 | 1111 |
| 1128 // Emit function patching code. This will be swapped with the first 3 | |
| 1129 // instructions at entry point. | |
| 1130 patch_code_pc_offset_ = assembler()->CodeSize(); | |
| 1131 __ BranchPatchable(*StubCode::FixCallersTarget_entry()); | |
| 1132 | |
| 1133 if (is_optimizing()) { | 1112 if (is_optimizing()) { |
| 1134 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1113 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
| 1135 __ BranchPatchable(*StubCode::DeoptimizeLazy_entry()); | 1114 __ BranchPatchable(*StubCode::DeoptimizeLazy_entry()); |
| 1136 } | 1115 } |
| 1137 } | 1116 } |
| 1138 | 1117 |
| 1139 | 1118 |
| 1140 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1119 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
| 1141 const StubEntry& stub_entry, | 1120 const StubEntry& stub_entry, |
| 1142 RawPcDescriptors::Kind kind, | 1121 RawPcDescriptors::Kind kind, |
| (...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1832 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1811 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1833 __ PopDouble(reg); | 1812 __ PopDouble(reg); |
| 1834 } | 1813 } |
| 1835 | 1814 |
| 1836 | 1815 |
| 1837 #undef __ | 1816 #undef __ |
| 1838 | 1817 |
| 1839 } // namespace dart | 1818 } // namespace dart |
| 1840 | 1819 |
| 1841 #endif // defined TARGET_ARCH_ARM64 | 1820 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |