OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 }; | 131 }; |
132 | 132 |
133 | 133 |
134 namespace { | 134 namespace { |
135 | 135 |
136 bool HasImmediateInput(Instruction* instr, int index) { | 136 bool HasImmediateInput(Instruction* instr, int index) { |
137 return instr->InputAt(index)->IsImmediate(); | 137 return instr->InputAt(index)->IsImmediate(); |
138 } | 138 } |
139 | 139 |
140 | 140 |
141 class OutOfLineLoadInteger FINAL : public OutOfLineCode { | 141 class OutOfLineLoadZero FINAL : public OutOfLineCode { |
142 public: | 142 public: |
143 OutOfLineLoadInteger(CodeGenerator* gen, Register result) | 143 OutOfLineLoadZero(CodeGenerator* gen, Register result) |
144 : OutOfLineCode(gen), result_(result) {} | 144 : OutOfLineCode(gen), result_(result) {} |
145 | 145 |
146 void Generate() FINAL { __ xorl(result_, result_); } | 146 void Generate() FINAL { __ xorl(result_, result_); } |
147 | 147 |
148 private: | 148 private: |
149 Register const result_; | 149 Register const result_; |
150 }; | 150 }; |
151 | 151 |
152 | 152 |
153 class OutOfLineLoadFloat FINAL : public OutOfLineCode { | 153 class OutOfLineLoadNaN FINAL : public OutOfLineCode { |
154 public: | 154 public: |
155 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result) | 155 OutOfLineLoadNaN(CodeGenerator* gen, XMMRegister result) |
156 : OutOfLineCode(gen), result_(result) {} | 156 : OutOfLineCode(gen), result_(result) {} |
157 | 157 |
158 void Generate() FINAL { __ pcmpeqd(result_, result_); } | 158 void Generate() FINAL { __ pcmpeqd(result_, result_); } |
159 | 159 |
160 private: | 160 private: |
161 XMMRegister const result_; | 161 XMMRegister const result_; |
162 }; | 162 }; |
163 | 163 |
164 | 164 |
165 class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { | 165 class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 if (instr->InputAt(1)->IsDoubleRegister()) { \ | 265 if (instr->InputAt(1)->IsDoubleRegister()) { \ |
266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | 266 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ |
267 i.InputDoubleRegister(1)); \ | 267 i.InputDoubleRegister(1)); \ |
268 } else { \ | 268 } else { \ |
269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ | 269 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \ |
270 i.InputOperand(1)); \ | 270 i.InputOperand(1)); \ |
271 } \ | 271 } \ |
272 } while (0) | 272 } while (0) |
273 | 273 |
274 | 274 |
275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ | 275 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
276 do { \ | 276 do { \ |
277 auto result = i.OutputDoubleRegister(); \ | 277 auto result = i.OutputDoubleRegister(); \ |
278 auto offset = i.InputRegister(0); \ | 278 auto buffer = i.InputRegister(0); \ |
279 if (instr->InputAt(1)->IsRegister()) { \ | 279 auto index1 = i.InputRegister(1); \ |
280 __ cmpl(offset, i.InputRegister(1)); \ | 280 auto index2 = i.InputInt32(2); \ |
281 } else { \ | 281 OutOfLineCode* ool; \ |
282 __ cmpl(offset, i.InputImmediate(1)); \ | 282 if (instr->InputAt(3)->IsRegister()) { \ |
283 } \ | 283 auto length = i.InputRegister(3); \ |
284 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ | 284 DCHECK_EQ(0, index2); \ |
285 __ j(above_equal, ool->entry()); \ | 285 __ cmpl(index1, length); \ |
286 __ asm_instr(result, i.MemoryOperand(2)); \ | 286 ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
287 __ bind(ool->exit()); \ | 287 } else { \ |
288 } while (false) | 288 auto length = i.InputInt32(3); \ |
289 | 289 DCHECK_LE(index2, length); \ |
290 | 290 __ cmpl(index1, Immediate(length - index2)); \ |
291 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ | 291 if (index2 == 0) { \ |
292 do { \ | 292 ool = new (zone()) OutOfLineLoadNaN(this, result); \ |
293 auto result = i.OutputRegister(); \ | 293 } else { \ |
294 auto offset = i.InputRegister(0); \ | 294 class OutOfLineLoadFloat FINAL : public OutOfLineCode { \ |
295 if (instr->InputAt(1)->IsRegister()) { \ | 295 public: \ |
296 __ cmpl(offset, i.InputRegister(1)); \ | 296 OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result, \ |
297 } else { \ | 297 Register buffer, Register index1, int32_t index2, \ |
298 __ cmpl(offset, i.InputImmediate(1)); \ | 298 int32_t length) \ |
299 } \ | 299 : OutOfLineCode(gen), \ |
300 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ | 300 result_(result), \ |
301 __ j(above_equal, ool->entry()); \ | 301 buffer_(buffer), \ |
302 __ asm_instr(result, i.MemoryOperand(2)); \ | 302 index1_(index1), \ |
303 __ bind(ool->exit()); \ | 303 index2_(index2), \ |
304 } while (false) | 304 length_(length) {} \ |
305 | 305 \ |
306 | 306 void Generate() FINAL { \ |
307 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ | 307 DCHECK_NE(0, index2_); \ |
308 do { \ | 308 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
309 auto offset = i.InputRegister(0); \ | 309 __ pcmpeqd(result_, result_); \ |
310 if (instr->InputAt(1)->IsRegister()) { \ | 310 __ cmpl(kScratchRegister, Immediate(length_)); \ |
311 __ cmpl(offset, i.InputRegister(1)); \ | 311 __ j(above_equal, exit()); \ |
312 } else { \ | 312 __ asm_instr(result_, \ |
313 __ cmpl(offset, i.InputImmediate(1)); \ | 313 Operand(buffer_, kScratchRegister, times_1, 0)); \ |
314 } \ | 314 } \ |
315 Label done; \ | 315 \ |
316 __ j(above_equal, &done, Label::kNear); \ | 316 private: \ |
317 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ | 317 XMMRegister const result_; \ |
318 __ bind(&done); \ | 318 Register const buffer_; \ |
319 } while (false) | 319 Register const index1_; \ |
320 | 320 int32_t const index2_; \ |
321 | 321 int32_t const length_; \ |
322 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ | 322 }; \ |
323 do { \ | 323 ool = new (zone()) \ |
324 auto offset = i.InputRegister(0); \ | 324 OutOfLineLoadFloat(this, result, buffer, index1, index2, length); \ |
325 if (instr->InputAt(1)->IsRegister()) { \ | 325 } \ |
326 __ cmpl(offset, i.InputRegister(1)); \ | 326 } \ |
327 } else { \ | 327 __ j(above_equal, ool->entry()); \ |
328 __ cmpl(offset, i.InputImmediate(1)); \ | 328 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ |
329 } \ | 329 __ bind(ool->exit()); \ |
330 Label done; \ | 330 } while (false) |
331 __ j(above_equal, &done, Label::kNear); \ | 331 |
332 if (instr->InputAt(2)->IsRegister()) { \ | 332 |
333 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ | 333 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
334 } else { \ | 334 do { \ |
335 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ | 335 auto result = i.OutputRegister(); \ |
336 } \ | 336 auto buffer = i.InputRegister(0); \ |
337 __ bind(&done); \ | 337 auto index1 = i.InputRegister(1); \ |
338 } while (false) | 338 auto index2 = i.InputInt32(2); \ |
339 | 339 OutOfLineCode* ool; \ |
340 | 340 if (instr->InputAt(3)->IsRegister()) { \ |
| 341 auto length = i.InputRegister(3); \ |
| 342 DCHECK_EQ(0, index2); \ |
| 343 __ cmpl(index1, length); \ |
| 344 ool = new (zone()) OutOfLineLoadZero(this, result); \ |
| 345 } else { \ |
| 346 auto length = i.InputInt32(3); \ |
| 347 DCHECK_LE(index2, length); \ |
| 348 __ cmpl(index1, Immediate(length - index2)); \ |
| 349 if (index2 == 0) { \ |
| 350 ool = new (zone()) OutOfLineLoadZero(this, result); \ |
| 351 } else { \ |
| 352 class OutOfLineLoadInteger FINAL : public OutOfLineCode { \ |
| 353 public: \ |
| 354 OutOfLineLoadInteger(CodeGenerator* gen, Register result, \ |
| 355 Register buffer, Register index1, \ |
| 356 int32_t index2, int32_t length) \ |
| 357 : OutOfLineCode(gen), \ |
| 358 result_(result), \ |
| 359 buffer_(buffer), \ |
| 360 index1_(index1), \ |
| 361 index2_(index2), \ |
| 362 length_(length) {} \ |
| 363 \ |
| 364 void Generate() FINAL { \ |
| 365 DCHECK_NE(0, index2_); \ |
| 366 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
| 367 __ xorl(result_, result_); \ |
| 368 __ cmpl(kScratchRegister, Immediate(length_)); \ |
| 369 __ j(above_equal, exit()); \ |
| 370 __ asm_instr(result_, \ |
| 371 Operand(buffer_, kScratchRegister, times_1, 0)); \ |
| 372 } \ |
| 373 \ |
| 374 private: \ |
| 375 Register const result_; \ |
| 376 Register const buffer_; \ |
| 377 Register const index1_; \ |
| 378 int32_t const index2_; \ |
| 379 int32_t const length_; \ |
| 380 }; \ |
| 381 ool = new (zone()) OutOfLineLoadInteger(this, result, buffer, index1, \ |
| 382 index2, length); \ |
| 383 } \ |
| 384 } \ |
| 385 __ j(above_equal, ool->entry()); \ |
| 386 __ asm_instr(result, Operand(buffer, index1, times_1, index2)); \ |
| 387 __ bind(ool->exit()); \ |
| 388 } while (false) |
| 389 |
| 390 |
| 391 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ |
| 392 do { \ |
| 393 auto buffer = i.InputRegister(0); \ |
| 394 auto index1 = i.InputRegister(1); \ |
| 395 auto index2 = i.InputInt32(2); \ |
| 396 auto value = i.InputDoubleRegister(4); \ |
| 397 if (instr->InputAt(3)->IsRegister()) { \ |
| 398 auto length = i.InputRegister(3); \ |
| 399 DCHECK_EQ(0, index2); \ |
| 400 Label done; \ |
| 401 __ cmpl(index1, length); \ |
| 402 __ j(above_equal, &done, Label::kNear); \ |
| 403 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 404 __ bind(&done); \ |
| 405 } else { \ |
| 406 auto length = i.InputInt32(3); \ |
| 407 DCHECK_LE(index2, length); \ |
| 408 __ cmpl(index1, Immediate(length - index2)); \ |
| 409 if (index2 == 0) { \ |
| 410 Label done; \ |
| 411 __ j(above_equal, &done, Label::kNear); \ |
| 412 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 413 __ bind(&done); \ |
| 414 } else { \ |
| 415 class OutOfLineStoreFloat FINAL : public OutOfLineCode { \ |
| 416 public: \ |
| 417 OutOfLineStoreFloat(CodeGenerator* gen, Register buffer, \ |
| 418 Register index1, int32_t index2, int32_t length, \ |
| 419 XMMRegister value) \ |
| 420 : OutOfLineCode(gen), \ |
| 421 buffer_(buffer), \ |
| 422 index1_(index1), \ |
| 423 index2_(index2), \ |
| 424 length_(length), \ |
| 425 value_(value) {} \ |
| 426 \ |
| 427 void Generate() FINAL { \ |
| 428 DCHECK_NE(0, index2_); \ |
| 429 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
| 430 __ cmpl(kScratchRegister, Immediate(length_)); \ |
| 431 __ j(above_equal, exit()); \ |
| 432 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ |
| 433 value_); \ |
| 434 } \ |
| 435 \ |
| 436 private: \ |
| 437 Register const buffer_; \ |
| 438 Register const index1_; \ |
| 439 int32_t const index2_; \ |
| 440 int32_t const length_; \ |
| 441 XMMRegister const value_; \ |
| 442 }; \ |
| 443 auto ool = new (zone()) \ |
| 444 OutOfLineStoreFloat(this, buffer, index1, index2, length, value); \ |
| 445 __ j(above_equal, ool->entry()); \ |
| 446 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 447 __ bind(ool->exit()); \ |
| 448 } \ |
| 449 } \ |
| 450 } while (false) |
| 451 |
| 452 |
| 453 #define ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Value) \ |
| 454 do { \ |
| 455 auto buffer = i.InputRegister(0); \ |
| 456 auto index1 = i.InputRegister(1); \ |
| 457 auto index2 = i.InputInt32(2); \ |
| 458 if (instr->InputAt(3)->IsRegister()) { \ |
| 459 auto length = i.InputRegister(3); \ |
| 460 DCHECK_EQ(0, index2); \ |
| 461 Label done; \ |
| 462 __ cmpl(index1, length); \ |
| 463 __ j(above_equal, &done, Label::kNear); \ |
| 464 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 465 __ bind(&done); \ |
| 466 } else { \ |
| 467 auto length = i.InputInt32(3); \ |
| 468 DCHECK_LE(index2, length); \ |
| 469 __ cmpl(index1, Immediate(length - index2)); \ |
| 470 if (index2 == 0) { \ |
| 471 Label done; \ |
| 472 __ j(above_equal, &done, Label::kNear); \ |
| 473 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 474 __ bind(&done); \ |
| 475 } else { \ |
| 476 class OutOfLineStoreInteger FINAL : public OutOfLineCode { \ |
| 477 public: \ |
| 478 OutOfLineStoreInteger(CodeGenerator* gen, Register buffer, \ |
| 479 Register index1, int32_t index2, \ |
| 480 int32_t length, Value value) \ |
| 481 : OutOfLineCode(gen), \ |
| 482 buffer_(buffer), \ |
| 483 index1_(index1), \ |
| 484 index2_(index2), \ |
| 485 length_(length), \ |
| 486 value_(value) {} \ |
| 487 \ |
| 488 void Generate() FINAL { \ |
| 489 DCHECK_NE(0, index2_); \ |
| 490 __ leal(kScratchRegister, Operand(index1_, index2_)); \ |
| 491 __ cmpl(kScratchRegister, Immediate(length_)); \ |
| 492 __ j(above_equal, exit()); \ |
| 493 __ asm_instr(Operand(buffer_, kScratchRegister, times_1, 0), \ |
| 494 value_); \ |
| 495 } \ |
| 496 \ |
| 497 private: \ |
| 498 Register const buffer_; \ |
| 499 Register const index1_; \ |
| 500 int32_t const index2_; \ |
| 501 int32_t const length_; \ |
| 502 Value const value_; \ |
| 503 }; \ |
| 504 auto ool = new (zone()) OutOfLineStoreInteger(this, buffer, index1, \ |
| 505 index2, length, value); \ |
| 506 __ j(above_equal, ool->entry()); \ |
| 507 __ asm_instr(Operand(buffer, index1, times_1, index2), value); \ |
| 508 __ bind(ool->exit()); \ |
| 509 } \ |
| 510 } \ |
| 511 } while (false) |
| 512 |
| 513 |
| 514 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 515 do { \ |
| 516 if (instr->InputAt(4)->IsRegister()) { \ |
| 517 Register value = i.InputRegister(4); \ |
| 518 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Register); \ |
| 519 } else { \ |
| 520 Immediate value = i.InputImmediate(4); \ |
| 521 ASSEMBLE_CHECKED_STORE_INTEGER_IMPL(asm_instr, Immediate); \ |
| 522 } \ |
| 523 } while (false) |
| 524 |
| 525 |
341 // Assembles an instruction after register allocation, producing machine code. | 526 // Assembles an instruction after register allocation, producing machine code. |
342 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 527 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
343 X64OperandConverter i(this, instr); | 528 X64OperandConverter i(this, instr); |
344 | 529 |
345 switch (ArchOpcodeField::decode(instr->opcode())) { | 530 switch (ArchOpcodeField::decode(instr->opcode())) { |
346 case kArchCallCodeObject: { | 531 case kArchCallCodeObject: { |
347 EnsureSpaceForLazyDeopt(); | 532 EnsureSpaceForLazyDeopt(); |
348 if (HasImmediateInput(instr, 0)) { | 533 if (HasImmediateInput(instr, 0)) { |
349 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 534 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
350 __ Call(code, RelocInfo::CODE_TARGET); | 535 __ Call(code, RelocInfo::CODE_TARGET); |
(...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 } | 1437 } |
1253 } | 1438 } |
1254 MarkLazyDeoptSite(); | 1439 MarkLazyDeoptSite(); |
1255 } | 1440 } |
1256 | 1441 |
1257 #undef __ | 1442 #undef __ |
1258 | 1443 |
1259 } // namespace internal | 1444 } // namespace internal |
1260 } // namespace compiler | 1445 } // namespace compiler |
1261 } // namespace v8 | 1446 } // namespace v8 |
OLD | NEW |