Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (237626 => 237627)
--- trunk/Source/_javascript_Core/ChangeLog 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-10-31 06:14:04 UTC (rev 237627)
@@ -1,3 +1,24 @@
+2018-10-30 Yusuke Suzuki <[email protected]>
+
+ [JSC][LLInt] Compact LLInt ASM code by removing unnecessary instructions
+ https://bugs.webkit.org/show_bug.cgi?id=191092
+
+ Reviewed by Saam Barati.
+
+ Looking through LLIntAssembly.h, we can find several inefficiencies. This patch fixes the
+ following things to tighten LLInt ASM code.
+
+ 1. Remove unnecessary load instructions. Use jmp with BaseIndex directly.
+ 2. Introduce strength reduction for mul instructions in offlineasm layer. This is now critical
+ since mul instruction is executed in `metadata` operation in LLInt. If the given immediate is
+ a power of two, we convert it to lshift instruction.
+
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * offlineasm/arm64.rb:
+ * offlineasm/instructions.rb:
+ * offlineasm/x86.rb:
+
2018-10-30 Don Olmstead <[email protected]>
[PlayStation] Enable _javascript_Core
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (237626 => 237627)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2018-10-31 06:14:04 UTC (rev 237627)
@@ -26,15 +26,13 @@
macro nextInstruction()
loadb [PC], t0
leap _g_opcodeMap, t1
- loadp [t1, t0, 4], t2
- jmp t2, BytecodePtrTag
+ jmp [t1, t0, 4], BytecodePtrTag
end
macro nextInstructionWide()
loadi 1[PC], t0
leap _g_opcodeMapWide, t1
- loadp [t1, t0, 4], t2
- jmp t2, BytecodePtrTag
+ jmp [t1, t0, 4], BytecodePtrTag
end
macro getuOperandNarrow(op, field, dst)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (237626 => 237627)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2018-10-31 06:14:04 UTC (rev 237627)
@@ -28,15 +28,13 @@
macro nextInstruction()
loadb [PB, PC, 1], t0
leap _g_opcodeMap, t1
- loadp [t1, t0, PtrSize], t2
- jmp t2, BytecodePtrTag
+ jmp [t1, t0, PtrSize], BytecodePtrTag
end
macro nextInstructionWide()
loadi 1[PB, PC, 1], t0
leap _g_opcodeMapWide, t1
- loadp [t1, t0, PtrSize], t2
- jmp t2, BytecodePtrTag
+ jmp [t1, t0, PtrSize], BytecodePtrTag
end
macro getuOperandNarrow(op, field, dst)
@@ -437,17 +435,30 @@
# Index and value must be different registers. Index may be clobbered.
macro loadConstantOrVariable(size, index, value)
- size(FirstConstantRegisterIndexNarrow, FirstConstantRegisterIndexWide, macro (FirstConstantRegisterIndex)
- bpgteq index, FirstConstantRegisterIndex, .constant
+ macro loadNarrow()
+ bpgteq index, FirstConstantRegisterIndexNarrow, .constant
loadq [cfr, index, 8], value
jmp .done
.constant:
loadp CodeBlock[cfr], value
loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
- subp FirstConstantRegisterIndex, index
+ loadq -(FirstConstantRegisterIndexNarrow * 8)[value, index, 8], value
+ .done:
+ end
+
+ macro loadWide()
+ bpgteq index, FirstConstantRegisterIndexWide, .constant
+ loadq [cfr, index, 8], value
+ jmp .done
+ .constant:
+ loadp CodeBlock[cfr], value
+ loadp CodeBlock::m_constantRegisters + VectorBufferOffset[value], value
+ subp FirstConstantRegisterIndexWide, index
loadq [value, index, 8], value
.done:
- end)
+ end
+
+ size(loadNarrow, loadWide, macro (load) load() end)
end
macro loadConstantOrVariableInt32(size, index, value, slow)
Modified: trunk/Source/_javascript_Core/offlineasm/arm64.rb (237626 => 237627)
--- trunk/Source/_javascript_Core/offlineasm/arm64.rb 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/offlineasm/arm64.rb 2018-10-31 06:14:04 UTC (rev 237627)
@@ -484,6 +484,18 @@
$asm.puts "#{opcode} #{arm64TACOperands(operands, kind)}"
end
+def emitARM64Mul(opcode, operands, kind)
+ if operands.size == 2 and operands[0].is_a? Immediate
+ imm = operands[0].value
+ if imm > 0 and isPowerOfTwo(imm)
+ emitARM64LShift([Immediate.new(nil, Math.log2(imm).to_i), operands[1]], kind)
+ return
+ end
+ end
+
+ $asm.puts "madd #{arm64TACOperands(operands, kind)}, #{arm64GPRName('xzr', kind)}"
+end
+
def emitARM64Unflipped(opcode, operands, kind)
$asm.puts "#{opcode} #{arm64Operands(operands, kind)}"
end
@@ -522,6 +534,21 @@
emitARM64TAC(opcodeRegs, operands, kind)
end
+def emitARM64LShift(operands, kind)
+ emitARM64Shift("lslv", "ubfm", operands, kind) {
+ | value |
+ case kind
+ when :word
+ [32 - value, 31 - value]
+ when :ptr
+ bitSize = $currentSettings["ADDRESS64"] ? 64 : 32
+ [bitSize - value, bitSize - 1 - value]
+ when :quad
+ [64 - value, 63 - value]
+ end
+ }
+end
+
def emitARM64Branch(opcode, operands, kind, branchOpcode)
emitARM64Unflipped(opcode, operands[0..-2], kind)
$asm.puts "#{branchOpcode} #{operands[-1].asmLabel}"
@@ -584,21 +611,11 @@
when "xorq"
emitARM64TAC("eor", operands, :quad)
when "lshifti"
- emitARM64Shift("lslv", "ubfm", operands, :word) {
- | value |
- [32 - value, 31 - value]
- }
+ emitARM64LShift(operands, :word)
when "lshiftp"
- emitARM64Shift("lslv", "ubfm", operands, :ptr) {
- | value |
- bitSize = $currentSettings["ADDRESS64"] ? 64 : 32
- [bitSize - value, bitSize - 1 - value]
- }
+ emitARM64LShift(operands, :ptr)
when "lshiftq"
- emitARM64Shift("lslv", "ubfm", operands, :quad) {
- | value |
- [64 - value, 63 - value]
- }
+ emitARM64LShift(operands, :quad)
when "rshifti"
emitARM64Shift("asrv", "sbfm", operands, :word) {
| value |
@@ -632,11 +649,11 @@
[value, 63]
}
when "muli"
- $asm.puts "madd #{arm64TACOperands(operands, :word)}, wzr"
+ emitARM64Mul('mul', operands, :word)
when "mulp"
- $asm.puts "madd #{arm64TACOperands(operands, :ptr)}, #{arm64GPRName('xzr', :ptr)}"
+ emitARM64Mul('mul', operands, :ptr)
when "mulq"
- $asm.puts "madd #{arm64TACOperands(operands, :quad)}, xzr"
+ emitARM64Mul('mul', operands, :quad)
when "subi"
emitARM64TAC("sub", operands, :word)
when "subp"
Modified: trunk/Source/_javascript_Core/offlineasm/instructions.rb (237626 => 237627)
--- trunk/Source/_javascript_Core/offlineasm/instructions.rb 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/offlineasm/instructions.rb 2018-10-31 06:14:04 UTC (rev 237627)
@@ -324,3 +324,7 @@
instruction != "ret" and instruction != "jmp"
end
+def isPowerOfTwo(value)
+ return false if value <= 0
+ (value & (value - 1)).zero?
+end
Modified: trunk/Source/_javascript_Core/offlineasm/x86.rb (237626 => 237627)
--- trunk/Source/_javascript_Core/offlineasm/x86.rb 2018-10-31 05:45:07 UTC (rev 237626)
+++ trunk/Source/_javascript_Core/offlineasm/x86.rb 2018-10-31 06:14:04 UTC (rev 237627)
@@ -798,11 +798,18 @@
def handleX86Mul(kind)
if operands.size == 3 and operands[0].is_a? Immediate
$asm.puts "imul#{x86Suffix(kind)} #{x86Operands(kind, kind, kind)}"
- else
- # FIXME: could do some peephole in case the left operand is immediate and it's
- # a power of two.
- handleX86Op("imul#{x86Suffix(kind)}", kind)
+ return
end
+
+ if operands.size == 2 and operands[0].is_a? Immediate
+ imm = operands[0].value
+ if imm > 0 and isPowerOfTwo(imm)
+ $asm.puts "sal#{x86Suffix(kind)} #{orderOperands(Immediate.new(nil, Math.log2(imm).to_i).x86Operand(kind), operands[1].x86Operand(kind))}"
+ return
+ end
+ end
+
+ handleX86Op("imul#{x86Suffix(kind)}", kind)
end
def handleX86Peek()