OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 intptr_t slot_ix = 0; | 59 intptr_t slot_ix = 0; |
60 Environment* current = deopt_env_; | 60 Environment* current = deopt_env_; |
61 | 61 |
62 // Emit all kMaterializeObject instructions describing objects to be | 62 // Emit all kMaterializeObject instructions describing objects to be |
63 // materialized on the deoptimization as a prefix to the deoptimization info. | 63 // materialized on the deoptimization as a prefix to the deoptimization info. |
64 EmitMaterializations(deopt_env_, builder); | 64 EmitMaterializations(deopt_env_, builder); |
65 | 65 |
66 // The real frame starts here. | 66 // The real frame starts here. |
67 builder->MarkFrameStart(); | 67 builder->MarkFrameStart(); |
68 | 68 |
69 // Callee's PC marker is not used anymore. Pass Function::null() to set to 0. | 69 // Current PP, FP, and PC. |
| 70 builder->AddPp(current->function(), slot_ix++); |
70 builder->AddPcMarker(Function::Handle(), slot_ix++); | 71 builder->AddPcMarker(Function::Handle(), slot_ix++); |
71 | |
72 // Current FP and PC. | |
73 builder->AddCallerFp(slot_ix++); | 72 builder->AddCallerFp(slot_ix++); |
74 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); | 73 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); |
75 | 74 |
76 // Emit all values that are needed for materialization as a part of the | 75 // Emit all values that are needed for materialization as a part of the |
77 // expression stack for the bottom-most frame. This guarantees that GC | 76 // expression stack for the bottom-most frame. This guarantees that GC |
78 // will be able to find them during materialization. | 77 // will be able to find them during materialization. |
79 slot_ix = builder->EmitMaterializationArguments(slot_ix); | 78 slot_ix = builder->EmitMaterializationArguments(slot_ix); |
80 | 79 |
81 // For the innermost environment, set outgoing arguments and the locals. | 80 // For the innermost environment, set outgoing arguments and the locals. |
82 for (intptr_t i = current->Length() - 1; | 81 for (intptr_t i = current->Length() - 1; |
83 i >= current->fixed_parameter_count(); | 82 i >= current->fixed_parameter_count(); |
84 i--) { | 83 i--) { |
85 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); | 84 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); |
86 } | 85 } |
87 | 86 |
88 // Current PC marker and caller FP. | |
89 builder->AddPcMarker(current->function(), slot_ix++); | |
90 builder->AddCallerFp(slot_ix++); | |
91 | |
92 Environment* previous = current; | 87 Environment* previous = current; |
93 current = current->outer(); | 88 current = current->outer(); |
94 while (current != NULL) { | 89 while (current != NULL) { |
| 90 // PP, FP, and PC. |
| 91 builder->AddPp(current->function(), slot_ix++); |
| 92 builder->AddPcMarker(previous->function(), slot_ix++); |
| 93 builder->AddCallerFp(slot_ix++); |
| 94 |
95 // For any outer environment the deopt id is that of the call instruction | 95 // For any outer environment the deopt id is that of the call instruction |
96 // which is recorded in the outer environment. | 96 // which is recorded in the outer environment. |
97 builder->AddReturnAddress(current->function(), | 97 builder->AddReturnAddress(current->function(), |
98 Isolate::ToDeoptAfter(current->deopt_id()), | 98 Isolate::ToDeoptAfter(current->deopt_id()), |
99 slot_ix++); | 99 slot_ix++); |
100 | 100 |
101 // The values of outgoing arguments can be changed from the inlined call so | 101 // The values of outgoing arguments can be changed from the inlined call so |
102 // we must read them from the previous environment. | 102 // we must read them from the previous environment. |
103 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { | 103 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
104 builder->AddCopy(previous->ValueAt(i), | 104 builder->AddCopy(previous->ValueAt(i), |
105 previous->LocationAt(i), | 105 previous->LocationAt(i), |
106 slot_ix++); | 106 slot_ix++); |
107 } | 107 } |
108 | 108 |
109 // Set the locals, note that outgoing arguments are not in the environment. | 109 // Set the locals, note that outgoing arguments are not in the environment. |
110 for (intptr_t i = current->Length() - 1; | 110 for (intptr_t i = current->Length() - 1; |
111 i >= current->fixed_parameter_count(); | 111 i >= current->fixed_parameter_count(); |
112 i--) { | 112 i--) { |
113 builder->AddCopy(current->ValueAt(i), | 113 builder->AddCopy(current->ValueAt(i), |
114 current->LocationAt(i), | 114 current->LocationAt(i), |
115 slot_ix++); | 115 slot_ix++); |
116 } | 116 } |
117 | 117 |
118 // PC marker and caller FP. | |
119 builder->AddPcMarker(current->function(), slot_ix++); | |
120 builder->AddCallerFp(slot_ix++); | |
121 | |
122 // Iterate on the outer environment. | 118 // Iterate on the outer environment. |
123 previous = current; | 119 previous = current; |
124 current = current->outer(); | 120 current = current->outer(); |
125 } | 121 } |
126 // The previous pointer is now the outermost environment. | 122 // The previous pointer is now the outermost environment. |
127 ASSERT(previous != NULL); | 123 ASSERT(previous != NULL); |
128 | 124 |
129 // For the outermost environment, set caller PC. | 125 // For the outermost environment, set caller PC, caller PP, and caller FP. |
| 126 builder->AddCallerPp(slot_ix++); |
| 127 // PC marker. |
| 128 builder->AddPcMarker(previous->function(), slot_ix++); |
| 129 builder->AddCallerFp(slot_ix++); |
130 builder->AddCallerPc(slot_ix++); | 130 builder->AddCallerPc(slot_ix++); |
131 | 131 |
132 // For the outermost environment, set the incoming arguments. | 132 // For the outermost environment, set the incoming arguments. |
133 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { | 133 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
134 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); | 134 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); |
135 } | 135 } |
136 | 136 |
137 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo()); | 137 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo()); |
138 return deopt_info.raw(); | 138 return deopt_info.raw(); |
139 } | 139 } |
140 | 140 |
141 | |
142 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 141 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
143 intptr_t stub_ix) { | 142 intptr_t stub_ix) { |
144 // Calls do not need stubs, they share a deoptimization trampoline. | 143 // Calls do not need stubs, they share a deoptimization trampoline. |
145 ASSERT(reason() != kDeoptAtCall); | 144 ASSERT(reason() != kDeoptAtCall); |
146 Assembler* assem = compiler->assembler(); | 145 Assembler* assem = compiler->assembler(); |
147 #define __ assem-> | 146 #define __ assem-> |
148 __ Comment("Deopt stub for id %" Pd "", deopt_id()); | 147 __ Comment("Deopt stub for id %" Pd "", deopt_id()); |
149 __ Bind(entry_label()); | 148 __ Bind(entry_label()); |
150 if (FLAG_trap_on_deoptimization) __ int3(); | 149 if (FLAG_trap_on_deoptimization) __ int3(); |
151 | 150 |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 } | 1008 } |
1010 | 1009 |
1011 __ Bind(&wrong_num_arguments); | 1010 __ Bind(&wrong_num_arguments); |
1012 if (function.IsClosureFunction()) { | 1011 if (function.IsClosureFunction()) { |
1013 // Invoke noSuchMethod function passing "call" as the original name. | 1012 // Invoke noSuchMethod function passing "call" as the original name. |
1014 const int kNumArgsChecked = 1; | 1013 const int kNumArgsChecked = 1; |
1015 const ICData& ic_data = ICData::ZoneHandle( | 1014 const ICData& ic_data = ICData::ZoneHandle( |
1016 ICData::New(function, Symbols::Call(), Object::empty_array(), | 1015 ICData::New(function, Symbols::Call(), Object::empty_array(), |
1017 Isolate::kNoDeoptId, kNumArgsChecked)); | 1016 Isolate::kNoDeoptId, kNumArgsChecked)); |
1018 __ LoadObject(RBX, ic_data); | 1017 __ LoadObject(RBX, ic_data); |
1019 __ LeaveFrame(); // The arguments are still on the stack. | 1018 __ LeaveFrame(true); // The arguments are still on the stack. |
1020 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1019 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
1021 // The noSuchMethod call may return to the caller, but not here. | 1020 // The noSuchMethod call may return to the caller, but not here. |
1022 __ int3(); | 1021 __ int3(); |
1023 } else if (check_correct_named_args) { | 1022 } else if (check_correct_named_args) { |
1024 __ Stop("Wrong arguments"); | 1023 __ Stop("Wrong arguments"); |
1025 } | 1024 } |
1026 | 1025 |
1027 __ Bind(&all_arguments_processed); | 1026 __ Bind(&all_arguments_processed); |
1028 // Nullify originally passed arguments only after they have been copied and | 1027 // Nullify originally passed arguments only after they have been copied and |
1029 // checked, otherwise noSuchMethod would not see their original values. | 1028 // checked, otherwise noSuchMethod would not see their original values. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 __ ret(); | 1069 __ ret(); |
1071 } | 1070 } |
1072 | 1071 |
1073 | 1072 |
1074 void FlowGraphCompiler::EmitFrameEntry() { | 1073 void FlowGraphCompiler::EmitFrameEntry() { |
1075 const Function& function = parsed_function().function(); | 1074 const Function& function = parsed_function().function(); |
1076 if (CanOptimizeFunction() && | 1075 if (CanOptimizeFunction() && |
1077 function.is_optimizable() && | 1076 function.is_optimizable() && |
1078 (!is_optimizing() || may_reoptimize())) { | 1077 (!is_optimizing() || may_reoptimize())) { |
1079 const Register function_reg = RDI; | 1078 const Register function_reg = RDI; |
| 1079 |
| 1080 |
| 1081 // Temporarily load pool pointer. |
| 1082 __ pushq(PP); // Preserve PP of caller. |
| 1083 __ LoadPoolPointer(); |
1080 __ LoadObject(function_reg, function); | 1084 __ LoadObject(function_reg, function); |
| 1085 __ popq(PP); // Restore PP of caller. |
| 1086 |
1081 // Patch point is after the eventually inlined function object. | 1087 // Patch point is after the eventually inlined function object. |
1082 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1088 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
1083 Isolate::kNoDeoptId, | 1089 Isolate::kNoDeoptId, |
1084 0); // No token position. | 1090 0); // No token position. |
1085 if (is_optimizing()) { | 1091 if (is_optimizing()) { |
1086 // Reoptimization of an optimized function is triggered by counting in | 1092 // Reoptimization of an optimized function is triggered by counting in |
1087 // IC stubs, but not at the entry of the function. | 1093 // IC stubs, but not at the entry of the function. |
1088 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), | 1094 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), |
1089 Immediate(FLAG_reoptimization_counter_threshold)); | 1095 Immediate(FLAG_reoptimization_counter_threshold)); |
1090 } else { | 1096 } else { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 // For closure functions, use "call" as the original name. | 1169 // For closure functions, use "call" as the original name. |
1164 const String& name = | 1170 const String& name = |
1165 String::Handle(function.IsClosureFunction() | 1171 String::Handle(function.IsClosureFunction() |
1166 ? Symbols::Call().raw() | 1172 ? Symbols::Call().raw() |
1167 : function.name()); | 1173 : function.name()); |
1168 const int kNumArgsChecked = 1; | 1174 const int kNumArgsChecked = 1; |
1169 const ICData& ic_data = ICData::ZoneHandle( | 1175 const ICData& ic_data = ICData::ZoneHandle( |
1170 ICData::New(function, name, Object::empty_array(), | 1176 ICData::New(function, name, Object::empty_array(), |
1171 Isolate::kNoDeoptId, kNumArgsChecked)); | 1177 Isolate::kNoDeoptId, kNumArgsChecked)); |
1172 __ LoadObject(RBX, ic_data); | 1178 __ LoadObject(RBX, ic_data); |
1173 __ LeaveFrame(); // The arguments are still on the stack. | 1179 __ LeaveFrame(true); // The arguments are still on the stack. |
1174 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); | 1180 __ jmp(&StubCode::CallNoSuchMethodFunctionLabel()); |
1175 // The noSuchMethod call may return to the caller, but not here. | 1181 // The noSuchMethod call may return to the caller, but not here. |
1176 __ int3(); | 1182 __ int3(); |
1177 } else { | 1183 } else { |
1178 __ Stop("Wrong number of arguments"); | 1184 __ Stop("Wrong number of arguments"); |
1179 } | 1185 } |
1180 __ Bind(&correct_num_arguments); | 1186 __ Bind(&correct_num_arguments); |
1181 } | 1187 } |
1182 } else if (!flow_graph().IsCompiledForOsr()) { | 1188 } else if (!flow_graph().IsCompiledForOsr()) { |
1183 CopyParameters(); | 1189 CopyParameters(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 Isolate::kNoDeoptId, | 1228 Isolate::kNoDeoptId, |
1223 0); // No token position. | 1229 0); // No token position. |
1224 __ jmp(&StubCode::DeoptimizeLazyLabel()); | 1230 __ jmp(&StubCode::DeoptimizeLazyLabel()); |
1225 } | 1231 } |
1226 | 1232 |
1227 | 1233 |
1228 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1234 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1229 const ExternalLabel* label, | 1235 const ExternalLabel* label, |
1230 PcDescriptors::Kind kind, | 1236 PcDescriptors::Kind kind, |
1231 LocationSummary* locs) { | 1237 LocationSummary* locs) { |
1232 __ call(label); | 1238 __ CallPatchable(label); |
1233 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1239 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
1234 RecordSafepoint(locs); | 1240 RecordSafepoint(locs); |
1235 } | 1241 } |
1236 | 1242 |
1237 | 1243 |
1238 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1244 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
1239 intptr_t token_pos, | 1245 intptr_t token_pos, |
1240 const ExternalLabel* label, | 1246 const ExternalLabel* label, |
1241 PcDescriptors::Kind kind, | 1247 PcDescriptors::Kind kind, |
1242 LocationSummary* locs) { | 1248 LocationSummary* locs) { |
1243 __ call(label); | 1249 __ CallPatchable(label); |
1244 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1250 AddCurrentDescriptor(kind, deopt_id, token_pos); |
1245 RecordSafepoint(locs); | 1251 RecordSafepoint(locs); |
1246 // Marks either the continuation point in unoptimized code or the | 1252 // Marks either the continuation point in unoptimized code or the |
1247 // deoptimization point in optimized code, after call. | 1253 // deoptimization point in optimized code, after call. |
1248 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1254 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1249 if (is_optimizing()) { | 1255 if (is_optimizing()) { |
1250 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1256 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1251 } else { | 1257 } else { |
1252 // Add deoptimization continuation point after the call and before the | 1258 // Add deoptimization continuation point after the call and before the |
1253 // arguments are removed. | 1259 // arguments are removed. |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 BranchInstr* branch) { | 1612 BranchInstr* branch) { |
1607 ASSERT(branch != NULL); | 1613 ASSERT(branch != NULL); |
1608 assembler()->comisd(left, right); | 1614 assembler()->comisd(left, right); |
1609 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? | 1615 BlockEntryInstr* nan_result = (true_condition == NOT_EQUAL) ? |
1610 branch->true_successor() : branch->false_successor(); | 1616 branch->true_successor() : branch->false_successor(); |
1611 assembler()->j(PARITY_EVEN, GetJumpLabel(nan_result)); | 1617 assembler()->j(PARITY_EVEN, GetJumpLabel(nan_result)); |
1612 branch->EmitBranchOnCondition(this, true_condition); | 1618 branch->EmitBranchOnCondition(this, true_condition); |
1613 } | 1619 } |
1614 | 1620 |
1615 | 1621 |
1616 | |
1617 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, | 1622 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, |
1618 FpuRegister left, | 1623 FpuRegister left, |
1619 FpuRegister right, | 1624 FpuRegister right, |
1620 Register result) { | 1625 Register result) { |
1621 assembler()->comisd(left, right); | 1626 assembler()->comisd(left, right); |
1622 Label is_false, is_true, done; | 1627 Label is_false, is_true, done; |
1623 assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false; | 1628 assembler()->j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN false; |
1624 assembler()->j(true_condition, &is_true, Assembler::kNearJump); | 1629 assembler()->j(true_condition, &is_true, Assembler::kNearJump); |
1625 assembler()->Bind(&is_false); | 1630 assembler()->Bind(&is_false); |
1626 assembler()->LoadObject(result, Bool::False()); | 1631 assembler()->LoadObject(result, Bool::False()); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1889 __ movups(reg, Address(RSP, 0)); | 1894 __ movups(reg, Address(RSP, 0)); |
1890 __ addq(RSP, Immediate(kFpuRegisterSize)); | 1895 __ addq(RSP, Immediate(kFpuRegisterSize)); |
1891 } | 1896 } |
1892 | 1897 |
1893 | 1898 |
1894 #undef __ | 1899 #undef __ |
1895 | 1900 |
1896 } // namespace dart | 1901 } // namespace dart |
1897 | 1902 |
1898 #endif // defined TARGET_ARCH_X64 | 1903 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |