| 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/ia32/assembler-ia32.h" | 10 #include "src/ia32/assembler-ia32.h" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 return ToOperand(instr_->InputAt(index), extra); | 31 return ToOperand(instr_->InputAt(index), extra); |
| 32 } | 32 } |
| 33 | 33 |
| 34 Immediate InputImmediate(size_t index) { | 34 Immediate InputImmediate(size_t index) { |
| 35 return ToImmediate(instr_->InputAt(index)); | 35 return ToImmediate(instr_->InputAt(index)); |
| 36 } | 36 } |
| 37 | 37 |
| 38 Operand OutputOperand() { return ToOperand(instr_->Output()); } | 38 Operand OutputOperand() { return ToOperand(instr_->Output()); } |
| 39 | 39 |
| 40 Operand ToOperand(InstructionOperand* op, int extra = 0) { | 40 Operand ToOperand(InstructionOperand* op, int extra = 0) { |
| 41 if (op->IsRegister()) { | 41 if (op->GeneratesRegister()) { |
| 42 DCHECK(extra == 0); | 42 DCHECK(extra == 0); |
| 43 return Operand(ToRegister(op)); | 43 return Operand(ToRegister(op)); |
| 44 } else if (op->IsDoubleRegister()) { | 44 } else if (op->IsDoubleRegister()) { |
| 45 DCHECK(extra == 0); | 45 DCHECK(extra == 0); |
| 46 return Operand(ToDoubleRegister(op)); | 46 return Operand(ToDoubleRegister(op)); |
| 47 } | 47 } |
| 48 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); | 48 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
| 49 // The linkage computes where all spill slots are located. | 49 // The linkage computes where all spill slots are located. |
| 50 FrameOffset offset = linkage()->GetFrameOffset( | 50 FrameOffset offset = linkage()->GetFrameOffset( |
| 51 AllocatedOperand::cast(op)->index(), frame(), extra); | 51 AllocatedOperand::cast(op)->index(), frame(), extra); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 XMMRegister const input_; | 215 XMMRegister const input_; |
| 216 }; | 216 }; |
| 217 | 217 |
| 218 } // namespace | 218 } // namespace |
| 219 | 219 |
| 220 | 220 |
| 221 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ | 221 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr) \ |
| 222 do { \ | 222 do { \ |
| 223 auto result = i.OutputDoubleRegister(); \ | 223 auto result = i.OutputDoubleRegister(); \ |
| 224 auto offset = i.InputRegister(0); \ | 224 auto offset = i.InputRegister(0); \ |
| 225 if (instr->InputAt(1)->IsRegister()) { \ | 225 if (instr->InputAt(1)->GeneratesRegister()) { \ |
| 226 __ cmp(offset, i.InputRegister(1)); \ | 226 __ cmp(offset, i.InputRegister(1)); \ |
| 227 } else { \ | 227 } else { \ |
| 228 __ cmp(offset, i.InputImmediate(1)); \ | 228 __ cmp(offset, i.InputImmediate(1)); \ |
| 229 } \ | 229 } \ |
| 230 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ | 230 OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \ |
| 231 __ j(above_equal, ool->entry()); \ | 231 __ j(above_equal, ool->entry()); \ |
| 232 __ asm_instr(result, i.MemoryOperand(2)); \ | 232 __ asm_instr(result, i.MemoryOperand(2)); \ |
| 233 __ bind(ool->exit()); \ | 233 __ bind(ool->exit()); \ |
| 234 } while (false) | 234 } while (false) |
| 235 | 235 |
| 236 | 236 |
| 237 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ | 237 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ |
| 238 do { \ | 238 do { \ |
| 239 auto result = i.OutputRegister(); \ | 239 auto result = i.OutputRegister(); \ |
| 240 auto offset = i.InputRegister(0); \ | 240 auto offset = i.InputRegister(0); \ |
| 241 if (instr->InputAt(1)->IsRegister()) { \ | 241 if (instr->InputAt(1)->GeneratesRegister()) { \ |
| 242 __ cmp(offset, i.InputRegister(1)); \ | 242 __ cmp(offset, i.InputRegister(1)); \ |
| 243 } else { \ | 243 } else { \ |
| 244 __ cmp(offset, i.InputImmediate(1)); \ | 244 __ cmp(offset, i.InputImmediate(1)); \ |
| 245 } \ | 245 } \ |
| 246 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ | 246 OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \ |
| 247 __ j(above_equal, ool->entry()); \ | 247 __ j(above_equal, ool->entry()); \ |
| 248 __ asm_instr(result, i.MemoryOperand(2)); \ | 248 __ asm_instr(result, i.MemoryOperand(2)); \ |
| 249 __ bind(ool->exit()); \ | 249 __ bind(ool->exit()); \ |
| 250 } while (false) | 250 } while (false) |
| 251 | 251 |
| 252 | 252 |
| 253 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ | 253 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr) \ |
| 254 do { \ | 254 do { \ |
| 255 auto offset = i.InputRegister(0); \ | 255 auto offset = i.InputRegister(0); \ |
| 256 if (instr->InputAt(1)->IsRegister()) { \ | 256 if (instr->InputAt(1)->GeneratesRegister()) { \ |
| 257 __ cmp(offset, i.InputRegister(1)); \ | 257 __ cmp(offset, i.InputRegister(1)); \ |
| 258 } else { \ | 258 } else { \ |
| 259 __ cmp(offset, i.InputImmediate(1)); \ | 259 __ cmp(offset, i.InputImmediate(1)); \ |
| 260 } \ | 260 } \ |
| 261 Label done; \ | 261 Label done; \ |
| 262 __ j(above_equal, &done, Label::kNear); \ | 262 __ j(above_equal, &done, Label::kNear); \ |
| 263 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ | 263 __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \ |
| 264 __ bind(&done); \ | 264 __ bind(&done); \ |
| 265 } while (false) | 265 } while (false) |
| 266 | 266 |
| 267 | 267 |
| 268 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ | 268 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ |
| 269 do { \ | 269 do { \ |
| 270 auto offset = i.InputRegister(0); \ | 270 auto offset = i.InputRegister(0); \ |
| 271 if (instr->InputAt(1)->IsRegister()) { \ | 271 if (instr->InputAt(1)->GeneratesRegister()) { \ |
| 272 __ cmp(offset, i.InputRegister(1)); \ | 272 __ cmp(offset, i.InputRegister(1)); \ |
| 273 } else { \ | 273 } else { \ |
| 274 __ cmp(offset, i.InputImmediate(1)); \ | 274 __ cmp(offset, i.InputImmediate(1)); \ |
| 275 } \ | 275 } \ |
| 276 Label done; \ | 276 Label done; \ |
| 277 __ j(above_equal, &done, Label::kNear); \ | 277 __ j(above_equal, &done, Label::kNear); \ |
| 278 if (instr->InputAt(2)->IsRegister()) { \ | 278 if (instr->InputAt(2)->GeneratesRegister()) { \ |
| 279 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ | 279 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ |
| 280 } else { \ | 280 } else { \ |
| 281 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ | 281 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ |
| 282 } \ | 282 } \ |
| 283 __ bind(&done); \ | 283 __ bind(&done); \ |
| 284 } while (false) | 284 } while (false) |
| 285 | 285 |
| 286 | 286 |
| 287 void CodeGenerator::AssembleDeconstructActivationRecord() { | 287 void CodeGenerator::AssembleDeconstructActivationRecord() { |
| 288 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 288 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| (...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 __ ret(0); | 1354 __ ret(0); |
| 1355 } | 1355 } |
| 1356 } | 1356 } |
| 1357 | 1357 |
| 1358 | 1358 |
| 1359 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1359 void CodeGenerator::AssembleMove(InstructionOperand* source, |
| 1360 InstructionOperand* destination) { | 1360 InstructionOperand* destination) { |
| 1361 IA32OperandConverter g(this, NULL); | 1361 IA32OperandConverter g(this, NULL); |
| 1362 // Dispatch on the source and destination operand kinds. Not all | 1362 // Dispatch on the source and destination operand kinds. Not all |
| 1363 // combinations are possible. | 1363 // combinations are possible. |
| 1364 if (source->IsRegister()) { | 1364 if (source->GeneratesRegister()) { |
| 1365 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1365 DCHECK(destination->GeneratesRegister() || destination->IsStackSlot()); |
| 1366 Register src = g.ToRegister(source); | 1366 Register src = g.ToRegister(source); |
| 1367 Operand dst = g.ToOperand(destination); | 1367 Operand dst = g.ToOperand(destination); |
| 1368 __ mov(dst, src); | 1368 __ mov(dst, src); |
| 1369 } else if (source->IsStackSlot()) { | 1369 } else if (source->IsStackSlot()) { |
| 1370 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1370 DCHECK(destination->GeneratesRegister() || destination->IsStackSlot()); |
| 1371 Operand src = g.ToOperand(source); | 1371 Operand src = g.ToOperand(source); |
| 1372 if (destination->IsRegister()) { | 1372 if (destination->GeneratesRegister()) { |
| 1373 Register dst = g.ToRegister(destination); | 1373 Register dst = g.ToRegister(destination); |
| 1374 __ mov(dst, src); | 1374 __ mov(dst, src); |
| 1375 } else { | 1375 } else { |
| 1376 Operand dst = g.ToOperand(destination); | 1376 Operand dst = g.ToOperand(destination); |
| 1377 __ push(src); | 1377 __ push(src); |
| 1378 __ pop(dst); | 1378 __ pop(dst); |
| 1379 } | 1379 } |
| 1380 } else if (source->IsConstant()) { | 1380 } else if (source->IsConstant()) { |
| 1381 Constant src_constant = g.ToConstant(source); | 1381 Constant src_constant = g.ToConstant(source); |
| 1382 if (src_constant.type() == Constant::kHeapObject) { | 1382 if (src_constant.type() == Constant::kHeapObject) { |
| 1383 Handle<HeapObject> src = src_constant.ToHeapObject(); | 1383 Handle<HeapObject> src = src_constant.ToHeapObject(); |
| 1384 int offset; | 1384 int offset; |
| 1385 if (IsMaterializableFromFrame(src, &offset)) { | 1385 if (IsMaterializableFromFrame(src, &offset)) { |
| 1386 if (destination->IsRegister()) { | 1386 if (destination->GeneratesRegister()) { |
| 1387 Register dst = g.ToRegister(destination); | 1387 Register dst = g.ToRegister(destination); |
| 1388 __ mov(dst, Operand(ebp, offset)); | 1388 __ mov(dst, Operand(ebp, offset)); |
| 1389 } else { | 1389 } else { |
| 1390 DCHECK(destination->IsStackSlot()); | 1390 DCHECK(destination->IsStackSlot()); |
| 1391 Operand dst = g.ToOperand(destination); | 1391 Operand dst = g.ToOperand(destination); |
| 1392 __ push(Operand(ebp, offset)); | 1392 __ push(Operand(ebp, offset)); |
| 1393 __ pop(dst); | 1393 __ pop(dst); |
| 1394 } | 1394 } |
| 1395 } else if (destination->IsRegister()) { | 1395 } else if (destination->GeneratesRegister()) { |
| 1396 Register dst = g.ToRegister(destination); | 1396 Register dst = g.ToRegister(destination); |
| 1397 __ LoadHeapObject(dst, src); | 1397 __ LoadHeapObject(dst, src); |
| 1398 } else { | 1398 } else { |
| 1399 DCHECK(destination->IsStackSlot()); | 1399 DCHECK(destination->IsStackSlot()); |
| 1400 Operand dst = g.ToOperand(destination); | 1400 Operand dst = g.ToOperand(destination); |
| 1401 AllowDeferredHandleDereference embedding_raw_address; | 1401 AllowDeferredHandleDereference embedding_raw_address; |
| 1402 if (isolate()->heap()->InNewSpace(*src)) { | 1402 if (isolate()->heap()->InNewSpace(*src)) { |
| 1403 __ PushHeapObject(src); | 1403 __ PushHeapObject(src); |
| 1404 __ pop(dst); | 1404 __ pop(dst); |
| 1405 } else { | 1405 } else { |
| 1406 __ mov(dst, src); | 1406 __ mov(dst, src); |
| 1407 } | 1407 } |
| 1408 } | 1408 } |
| 1409 } else if (destination->IsRegister()) { | 1409 } else if (destination->GeneratesRegister()) { |
| 1410 Register dst = g.ToRegister(destination); | 1410 Register dst = g.ToRegister(destination); |
| 1411 __ Move(dst, g.ToImmediate(source)); | 1411 __ Move(dst, g.ToImmediate(source)); |
| 1412 } else if (destination->IsStackSlot()) { | 1412 } else if (destination->IsStackSlot()) { |
| 1413 Operand dst = g.ToOperand(destination); | 1413 Operand dst = g.ToOperand(destination); |
| 1414 __ Move(dst, g.ToImmediate(source)); | 1414 __ Move(dst, g.ToImmediate(source)); |
| 1415 } else if (src_constant.type() == Constant::kFloat32) { | 1415 } else if (src_constant.type() == Constant::kFloat32) { |
| 1416 // TODO(turbofan): Can we do better here? | 1416 // TODO(turbofan): Can we do better here? |
| 1417 uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32()); | 1417 uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32()); |
| 1418 if (destination->IsDoubleRegister()) { | 1418 if (destination->IsDoubleRegister()) { |
| 1419 XMMRegister dst = g.ToDoubleRegister(destination); | 1419 XMMRegister dst = g.ToDoubleRegister(destination); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 UNREACHABLE(); | 1464 UNREACHABLE(); |
| 1465 } | 1465 } |
| 1466 } | 1466 } |
| 1467 | 1467 |
| 1468 | 1468 |
| 1469 void CodeGenerator::AssembleSwap(InstructionOperand* source, | 1469 void CodeGenerator::AssembleSwap(InstructionOperand* source, |
| 1470 InstructionOperand* destination) { | 1470 InstructionOperand* destination) { |
| 1471 IA32OperandConverter g(this, NULL); | 1471 IA32OperandConverter g(this, NULL); |
| 1472 // Dispatch on the source and destination operand kinds. Not all | 1472 // Dispatch on the source and destination operand kinds. Not all |
| 1473 // combinations are possible. | 1473 // combinations are possible. |
| 1474 if (source->IsRegister() && destination->IsRegister()) { | 1474 if (source->GeneratesRegister() && destination->GeneratesRegister()) { |
| 1475 // Register-register. | 1475 // Register-register. |
| 1476 Register src = g.ToRegister(source); | 1476 Register src = g.ToRegister(source); |
| 1477 Register dst = g.ToRegister(destination); | 1477 Register dst = g.ToRegister(destination); |
| 1478 __ xchg(dst, src); | 1478 __ xchg(dst, src); |
| 1479 } else if (source->IsRegister() && destination->IsStackSlot()) { | 1479 } else if (source->GeneratesRegister() && destination->IsStackSlot()) { |
| 1480 // Register-memory. | 1480 // Register-memory. |
| 1481 __ xchg(g.ToRegister(source), g.ToOperand(destination)); | 1481 __ xchg(g.ToRegister(source), g.ToOperand(destination)); |
| 1482 } else if (source->IsStackSlot() && destination->IsStackSlot()) { | 1482 } else if (source->IsStackSlot() && destination->IsStackSlot()) { |
| 1483 // Memory-memory. | 1483 // Memory-memory. |
| 1484 Operand src = g.ToOperand(source); | 1484 Operand src = g.ToOperand(source); |
| 1485 Operand dst = g.ToOperand(destination); | 1485 Operand dst = g.ToOperand(destination); |
| 1486 __ push(dst); | 1486 __ push(dst); |
| 1487 __ push(src); | 1487 __ push(src); |
| 1488 __ pop(dst); | 1488 __ pop(dst); |
| 1489 __ pop(src); | 1489 __ pop(src); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 __ Nop(padding_size); | 1541 __ Nop(padding_size); |
| 1542 } | 1542 } |
| 1543 } | 1543 } |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 #undef __ | 1546 #undef __ |
| 1547 | 1547 |
| 1548 } // namespace compiler | 1548 } // namespace compiler |
| 1549 } // namespace internal | 1549 } // namespace internal |
| 1550 } // namespace v8 | 1550 } // namespace v8 |
| OLD | NEW |