| 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 |