OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 outputs[output_count++] = g.DefineSameAsFirst(node); | 344 outputs[output_count++] = g.DefineSameAsFirst(node); |
345 if (cont->IsSet()) { | 345 if (cont->IsSet()) { |
346 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 346 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
347 } | 347 } |
348 | 348 |
349 DCHECK_NE(0u, input_count); | 349 DCHECK_NE(0u, input_count); |
350 DCHECK_NE(0u, output_count); | 350 DCHECK_NE(0u, output_count); |
351 DCHECK_GE(arraysize(inputs), input_count); | 351 DCHECK_GE(arraysize(inputs), input_count); |
352 DCHECK_GE(arraysize(outputs), output_count); | 352 DCHECK_GE(arraysize(outputs), output_count); |
353 | 353 |
354 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 354 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
355 outputs, input_count, inputs); | 355 inputs); |
356 if (cont->IsBranch()) instr->MarkAsControl(); | |
357 } | 356 } |
358 | 357 |
359 | 358 |
360 // Shared routine for multiple binary operations. | 359 // Shared routine for multiple binary operations. |
361 static void VisitBinop(InstructionSelector* selector, Node* node, | 360 static void VisitBinop(InstructionSelector* selector, Node* node, |
362 InstructionCode opcode) { | 361 InstructionCode opcode) { |
363 FlagsContinuation cont; | 362 FlagsContinuation cont; |
364 VisitBinop(selector, node, opcode, &cont); | 363 VisitBinop(selector, node, opcode, &cont); |
365 } | 364 } |
366 | 365 |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 namespace { | 1025 namespace { |
1027 | 1026 |
1028 // Shared routine for multiple compare operations. | 1027 // Shared routine for multiple compare operations. |
1029 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1028 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1030 InstructionOperand left, InstructionOperand right, | 1029 InstructionOperand left, InstructionOperand right, |
1031 FlagsContinuation* cont) { | 1030 FlagsContinuation* cont) { |
1032 X64OperandGenerator g(selector); | 1031 X64OperandGenerator g(selector); |
1033 opcode = cont->Encode(opcode); | 1032 opcode = cont->Encode(opcode); |
1034 if (cont->IsBranch()) { | 1033 if (cont->IsBranch()) { |
1035 selector->Emit(opcode, g.NoOutput(), left, right, | 1034 selector->Emit(opcode, g.NoOutput(), left, right, |
1036 g.Label(cont->true_block()), | 1035 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1037 g.Label(cont->false_block()))->MarkAsControl(); | |
1038 } else { | 1036 } else { |
1039 DCHECK(cont->IsSet()); | 1037 DCHECK(cont->IsSet()); |
1040 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1038 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1041 } | 1039 } |
1042 } | 1040 } |
1043 | 1041 |
1044 | 1042 |
1045 // Shared routine for multiple compare operations. | 1043 // Shared routine for multiple compare operations. |
1046 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1044 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1047 Node* left, Node* right, FlagsContinuation* cont, | 1045 Node* left, Node* right, FlagsContinuation* cont, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { | 1080 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) { |
1083 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); | 1081 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node()); |
1084 ExternalReference js_stack_limit = | 1082 ExternalReference js_stack_limit = |
1085 ExternalReference::address_of_stack_limit(selector->isolate()); | 1083 ExternalReference::address_of_stack_limit(selector->isolate()); |
1086 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1084 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
1087 // Compare(Load(js_stack_limit), LoadStackPointer) | 1085 // Compare(Load(js_stack_limit), LoadStackPointer) |
1088 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1086 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
1089 InstructionCode opcode = cont->Encode(kX64StackCheck); | 1087 InstructionCode opcode = cont->Encode(kX64StackCheck); |
1090 if (cont->IsBranch()) { | 1088 if (cont->IsBranch()) { |
1091 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), | 1089 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
1092 g.Label(cont->false_block()))->MarkAsControl(); | 1090 g.Label(cont->false_block())); |
1093 } else { | 1091 } else { |
1094 DCHECK(cont->IsSet()); | 1092 DCHECK(cont->IsSet()); |
1095 selector->Emit(opcode, g.DefineAsRegister(cont->result())); | 1093 selector->Emit(opcode, g.DefineAsRegister(cont->result())); |
1096 } | 1094 } |
1097 return; | 1095 return; |
1098 } | 1096 } |
1099 } | 1097 } |
1100 VisitWordCompare(selector, node, kX64Cmp, cont); | 1098 VisitWordCompare(selector, node, kX64Cmp, cont); |
1101 } | 1099 } |
1102 | 1100 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1258 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1256 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1259 inputs[0] = index_operand; | 1257 inputs[0] = index_operand; |
1260 std::fill(&inputs[1], &inputs[input_count], default_operand); | 1258 std::fill(&inputs[1], &inputs[input_count], default_operand); |
1261 for (size_t index = 0; index < case_count; ++index) { | 1259 for (size_t index = 0; index < case_count; ++index) { |
1262 size_t value = case_values[index] - min_value; | 1260 size_t value = case_values[index] - min_value; |
1263 BasicBlock* branch = case_branches[index]; | 1261 BasicBlock* branch = case_branches[index]; |
1264 DCHECK_LE(0u, value); | 1262 DCHECK_LE(0u, value); |
1265 DCHECK_LT(value + 2, input_count); | 1263 DCHECK_LT(value + 2, input_count); |
1266 inputs[value + 2] = g.Label(branch); | 1264 inputs[value + 2] = g.Label(branch); |
1267 } | 1265 } |
1268 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1266 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1269 ->MarkAsControl(); | |
1270 return; | 1267 return; |
1271 } | 1268 } |
1272 | 1269 |
1273 // Generate a sequence of conditional jumps. | 1270 // Generate a sequence of conditional jumps. |
1274 size_t input_count = 2 + case_count * 2; | 1271 size_t input_count = 2 + case_count * 2; |
1275 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1272 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1276 inputs[0] = value_operand; | 1273 inputs[0] = value_operand; |
1277 inputs[1] = default_operand; | 1274 inputs[1] = default_operand; |
1278 for (size_t index = 0; index < case_count; ++index) { | 1275 for (size_t index = 0; index < case_count; ++index) { |
1279 int32_t value = case_values[index]; | 1276 int32_t value = case_values[index]; |
1280 BasicBlock* branch = case_branches[index]; | 1277 BasicBlock* branch = case_branches[index]; |
1281 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); | 1278 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
1282 inputs[index * 2 + 2 + 1] = g.Label(branch); | 1279 inputs[index * 2 + 2 + 1] = g.Label(branch); |
1283 } | 1280 } |
1284 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1281 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1285 ->MarkAsControl(); | |
1286 } | 1282 } |
1287 | 1283 |
1288 | 1284 |
1289 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1285 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1290 Node* user = node; | 1286 Node* user = node; |
1291 FlagsContinuation cont(kEqual, node); | 1287 FlagsContinuation cont(kEqual, node); |
1292 Int32BinopMatcher m(user); | 1288 Int32BinopMatcher m(user); |
1293 if (m.right().Is(0)) { | 1289 if (m.right().Is(0)) { |
1294 Node* value = m.left().node(); | 1290 Node* value = m.left().node(); |
1295 | 1291 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1485 if (CpuFeatures::IsSupported(SSE4_1)) { | 1481 if (CpuFeatures::IsSupported(SSE4_1)) { |
1486 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1482 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
1487 MachineOperatorBuilder::kFloat64RoundTruncate; | 1483 MachineOperatorBuilder::kFloat64RoundTruncate; |
1488 } | 1484 } |
1489 return flags; | 1485 return flags; |
1490 } | 1486 } |
1491 | 1487 |
1492 } // namespace compiler | 1488 } // namespace compiler |
1493 } // namespace internal | 1489 } // namespace internal |
1494 } // namespace v8 | 1490 } // namespace v8 |
OLD | NEW |