Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(888)

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.cc

Issue 1414183006: [turbofan] Avoid unnecessary write barriers and improve code generation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "src/base/adapters.h" 5 #include "src/base/adapters.h"
6 #include "src/compiler/instruction-selector-impl.h" 6 #include "src/compiler/instruction-selector-impl.h"
7 #include "src/compiler/node-matchers.h" 7 #include "src/compiler/node-matchers.h"
8 #include "src/compiler/node-properties.h" 8 #include "src/compiler/node-properties.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 } 208 }
209 209
210 210
211 void InstructionSelector::VisitStore(Node* node) { 211 void InstructionSelector::VisitStore(Node* node) {
212 IA32OperandGenerator g(this); 212 IA32OperandGenerator g(this);
213 Node* base = node->InputAt(0); 213 Node* base = node->InputAt(0);
214 Node* index = node->InputAt(1); 214 Node* index = node->InputAt(1);
215 Node* value = node->InputAt(2); 215 Node* value = node->InputAt(2);
216 216
217 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); 217 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
218 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
218 MachineType rep = RepresentationOf(store_rep.machine_type()); 219 MachineType rep = RepresentationOf(store_rep.machine_type());
219 if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
220 DCHECK_EQ(kRepTagged, rep);
221 // TODO(dcarney): refactor RecordWrite function to take temp registers
222 // and pass them here instead of using fixed regs
223 if (g.CanBeImmediate(index)) {
224 InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister()};
225 Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx),
226 g.UseImmediate(index), g.UseFixed(value, ecx), arraysize(temps),
227 temps);
228 } else {
229 InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
230 Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx),
231 g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
232 temps);
233 }
234 return;
235 }
236 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
237 220
238 ArchOpcode opcode; 221 ArchOpcode opcode;
239 switch (rep) { 222 switch (rep) {
240 case kRepFloat32: 223 case kRepFloat32:
241 opcode = kIA32Movss; 224 opcode = kIA32Movss;
242 break; 225 break;
243 case kRepFloat64: 226 case kRepFloat64:
244 opcode = kIA32Movsd; 227 opcode = kIA32Movsd;
245 break; 228 break;
246 case kRepBit: // Fall through. 229 case kRepBit: // Fall through.
247 case kRepWord8: 230 case kRepWord8:
248 opcode = kIA32Movb; 231 opcode = kIA32Movb;
249 break; 232 break;
250 case kRepWord16: 233 case kRepWord16:
251 opcode = kIA32Movw; 234 opcode = kIA32Movw;
252 break; 235 break;
253 case kRepTagged: // Fall through. 236 case kRepTagged: // Fall through.
254 case kRepWord32: 237 case kRepWord32:
255 opcode = kIA32Movl; 238 opcode = kIA32Movl;
256 break; 239 break;
257 default: 240 default:
258 UNREACHABLE(); 241 UNREACHABLE();
259 return; 242 return;
260 } 243 }
261 244
262 InstructionOperand val; 245 InstructionOperand val;
263 if (g.CanBeImmediate(value)) { 246 if (g.CanBeImmediate(value) && write_barrier_kind < kPointerWriteBarrier) {
247 // It's only beneficial to use an immediate if we don't also need the
248 // value for the write barrier below; otherwise it's cheaper to just
249 // load the value into a register once and use that register for both
250 // the store and the write barrier code.
264 val = g.UseImmediate(value); 251 val = g.UseImmediate(value);
265 } else if (rep == kRepWord8 || rep == kRepBit) { 252 } else if (rep == kRepWord8 || rep == kRepBit) {
266 val = g.UseByteRegister(value); 253 val = g.UseByteRegister(value);
267 } else { 254 } else {
268 val = g.UseRegister(value); 255 val = g.UseRegister(value);
269 } 256 }
270 257
271 InstructionOperand inputs[4]; 258 InstructionOperand inputs[4];
272 size_t input_count = 0; 259 size_t input_count = 0;
273 AddressingMode mode = 260 AddressingMode addressing_mode =
274 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); 261 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
275 InstructionCode code = opcode | AddressingModeField::encode(mode); 262 InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
276 inputs[input_count++] = val; 263 inputs[input_count++] = val;
277 Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs); 264 Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
265
266 if (write_barrier_kind != kNoWriteBarrier) {
267 DCHECK_EQ(kRepTagged, rep);
268 input_count = 0;
269 inputs[input_count++] = g.UseUniqueRegister(base);
270 if (g.CanBeImmediate(index)) {
271 inputs[input_count++] = g.UseImmediate(index);
272 addressing_mode = kMode_MRI;
273 } else {
274 inputs[input_count++] = g.UseUniqueRegister(index);
275 addressing_mode = kMode_MR1;
276 }
277 RecordWriteMode record_write_mode;
278 switch (write_barrier_kind) {
279 case kNoWriteBarrier:
280 UNREACHABLE();
281 break;
282 case kMapWriteBarrier:
283 record_write_mode = RecordWriteMode::kValueIsMap;
284 break;
285 case kPointerWriteBarrier:
286 inputs[input_count++] = g.UseUniqueRegister(value);
287 record_write_mode = RecordWriteMode::kValueIsPointer;
288 break;
289 case kFullWriteBarrier:
290 inputs[input_count++] = g.UseUniqueRegister(value);
291 record_write_mode = RecordWriteMode::kValueIsAny;
292 break;
293 }
294 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
295 size_t const temp_count = arraysize(temps);
296 InstructionCode code = kArchRecordWrite;
297 code |= AddressingModeField::encode(addressing_mode);
298 code |= MiscField::encode(static_cast<int>(record_write_mode));
299 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
300 }
278 } 301 }
279 302
280 303
281 void InstructionSelector::VisitCheckedLoad(Node* node) { 304 void InstructionSelector::VisitCheckedLoad(Node* node) {
282 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); 305 MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
283 MachineType typ = TypeOf(OpParameter<MachineType>(node)); 306 MachineType typ = TypeOf(OpParameter<MachineType>(node));
284 IA32OperandGenerator g(this); 307 IA32OperandGenerator g(this);
285 Node* const buffer = node->InputAt(0); 308 Node* const buffer = node->InputAt(0);
286 Node* const offset = node->InputAt(1); 309 Node* const offset = node->InputAt(1);
287 Node* const length = node->InputAt(2); 310 Node* const length = node->InputAt(2);
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 if (CpuFeatures::IsSupported(SSE4_1)) { 1276 if (CpuFeatures::IsSupported(SSE4_1)) {
1254 flags |= MachineOperatorBuilder::kFloat64RoundDown | 1277 flags |= MachineOperatorBuilder::kFloat64RoundDown |
1255 MachineOperatorBuilder::kFloat64RoundTruncate; 1278 MachineOperatorBuilder::kFloat64RoundTruncate;
1256 } 1279 }
1257 return flags; 1280 return flags;
1258 } 1281 }
1259 1282
1260 } // namespace compiler 1283 } // namespace compiler
1261 } // namespace internal 1284 } // namespace internal
1262 } // namespace v8 1285 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698