Git Product home page Git Product logo

llv8's Introduction

LLV8

LLV8 is an experimental top-tier compiler for V8. It leverages the power of LLVM MCJIT to produce highly optimized code. It is supposed to be used as a third tier for cases where it makes sense to spend more time compiling to achieve higher throughput.

LLV8 (backend) is implemented as a patch to V8 and it cannot function without the virtual machine. Although LLV8 is only a fraction of the entire patched VM, we also refer to the whole thing (our fork of V8) as LLV8.

LLV8 codebase effectively consists of two repositories, both of which are hosted at github:

Building LLV8

Building instructions can be found in the project's wiki. They are duplicated in this readme for convenience.

We are going to check out sources of LLV8 and the modified LLVM. V8 (and thus LLV8) comes with binaries of a clang compiler, so we are going to use it to build both LLVM and LLV8 to avoid linking problems.

Checking out LLV8

The easiest way is to follow the process of building regular V8, adding the LLV8 branch as a remote.

cd $LLV8_ROOT # Choose any directory you want. 
# E.g. cd /some/dir && export LLV8_ROOT=`pwd`

Install depot_tools:

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

Fetch all the code:

fetch v8
cd v8
git remote add llv8 https://github.com/ispras/llv8.git
git checkout -b llv8 llv8/llv8
gclient sync

Note that we don't run make yet, since first we need to build LLVM libraries to link against. We had to check out V8 first to obtain the clang compiler though.

LLVM

Check out and build our version of LLVM:

cd $LLV8_ROOT
git clone https://github.com/ispras/llvm-for-v8.git
mkdir build-llvm
cd build-llvm
export CC=$LLV8_ROOT/v8/third_party/llvm-build/Release+Asserts/bin/clang
export CXX=$LLV8_ROOT/v8/third_party/llvm-build/Release+Asserts/bin/clang++
../llvm-for-v8/configure --enable-assertions --enable-optimized --disable-zlib
make -j9
sudo make install # Note: this installs the built version of llvm system-wide.

You can in theory pass --prefix to configure or not install llvm at all and use it from the build directory, because all you need to build llv8 is the llvm-configure of this freshly built llvm in your $PATH. But this makes the subsequent compilation of llv8 a bit more involved (the C++ compiler spews warnings-errors as it compiles LLVM headers).

Building LLV8

Finally, run make (substitute "release" for "debug" if you'd like to test performance):

cd $LLV8_ROOT/v8
export LINK=$CXX
make x64.debug -j9 i18nsupport=off gdbjit=off

Project documentation

Design documentation, building and runnig insructions can be found on LLV8 wiki.

Usage example

Let's compile a simple piece of JavaScript code with LLV8.

cat > a-plus-b.js
var N = 10000; // Should be big enough to pass optimization threshold.

function foo(a, b) {
    return a + b;
}

var k = 1;
for (var i = 0; i < N; i++) {
    k += foo(i, i % k);
}

print(k);

Now run it through LLV8:

$LLV8_ROOT/v8/out/x64.debug/d8 a-plus-b.js --llvm-filter=*

It should spew a lot of debug information to stderr, mostly LLVM IR before and after various passes and disassembly. Here is an abridged stderr output:

...
====================vvv Module  AFTER optimization vvv====================
; ModuleID = '0'
target triple = "x86_64-unknown-linux-gnu"

define x86_64_v8cc i8* @"0"(i8* %pointer_0, i8* nocapture readnone, i8* nocapture readnone, i8* %pointer_1, i8* %pointer_2, i8* %pointer_3) #0 gc "v8-gc" {
BlockEntry0:
  tail call void (i64, i32, ...) @llvm.experimental.stackmap(i64 0, i32 0)
  %2 = ptrtoint i8* %pointer_2 to i64
  %3 = and i64 %2, 1
  %4 = icmp eq i64 %3, 0
  br i1 %4, label %BlockCont, label %DeoptBlock

BlockCont:                                        ; preds = %BlockEntry0
  %5 = ptrtoint i8* %pointer_1 to i64
  %6 = and i64 %5, 1
  %7 = icmp eq i64 %6, 0
  br i1 %7, label %BlockCont1, label %DeoptBlock2

DeoptBlock:                                       ; preds = %BlockEntry0
  %8 = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 1, i32 5, i8* null, i32 0, i8* %pointer_3, i8* %pointer_2, i8* %pointer_1, i8* %pointer_0)
  unreachable

BlockCont1:                                       ; preds = %BlockCont
  %9 = tail call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %2, i64 %5)
  %10 = extractvalue { i64, i1 } %9, 1
  br i1 %10, label %DeoptBlock4, label %BlockCont3

DeoptBlock2:                                      ; preds = %BlockCont
  %11 = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 2, i32 5, i8* null, i32 0, i8* %pointer_3, i8* %pointer_2, i8* %pointer_1, i8* %pointer_0)
  unreachable

BlockCont3:                                       ; preds = %BlockCont1
  %12 = extractvalue { i64, i1 } %9, 0
  %13 = inttoptr i64 %12 to i8*
  ret i8* %13

DeoptBlock4:                                      ; preds = %BlockCont1
  %14 = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 3, i32 5, i8* null, i32 0, i8* %pointer_3, i8* %pointer_2, i8* %pointer_1, i8* %pointer_0)
  unreachable
}

declare void @llvm.experimental.stackmap(i64, i32, ...)

declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)

; Function Attrs: nounwind readnone
declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64) #1

attributes #0 = { "no-frame-pointer-elim"="true" "put-constantpool-in-fn-section"="true" "put-jumptable-in-fn-section"="true" }
attributes #1 = { nounwind readnone }
====================^^^ Module  AFTER optimization ^^^====================
...
  Version: 1
  StackSizes:
      (off:48232192, size:24)
  Constants:
  Records:
      (#0, offset = 18, flags = 0, locations = [] live_outs = [])
      (#1, offset = 42, flags = 0, locations = [(Register, rcx, off:0, size:8), (Register, rdx, off:0, size:8), (Register, rbx, off:0, size:8), (Register, rsi, off:0, size:8), ] live_outs = [])
      (#2, offset = 47, flags = 0, locations = [(Register, rcx, off:0, size:8), (Register, rdx, off:0, size:8), (Register, rbx, off:0, size:8), (Register, rsi, off:0, size:8), ] live_outs = [])
      (#3, offset = 52, flags = 0, locations = [(Register, rcx, off:0, size:8), (Register, rdx, off:0, size:8), (Register, rbx, off:0, size:8), (Register, rsi, off:0, size:8), ] live_outs = [])
Instruction start: 0xa31d33a040
0xa31d33a040		push	rbp
0xa31d33a041		mov	rbp, rsp
0xa31d33a044		push	rsi
0xa31d33a045		push	rdi
0xa31d33a046		mov	rcx, qword ptr [rbp + 0x20]
0xa31d33a04a		mov	rdx, qword ptr [rbp + 0x18]
0xa31d33a04e		mov	rbx, qword ptr [rbp + 0x10]
0xa31d33a052		test	dl, 0x1
0xa31d33a055		jne	0x13
0xa31d33a057		test	bl, 0x1
0xa31d33a05a		jne	0x13
0xa31d33a05c		mov	rax, rdx
0xa31d33a05f		add	rax, rbx
0xa31d33a062		jo	0x10
0xa31d33a064		pop	rdi
0xa31d33a065		pop	rsi
0xa31d33a066		pop	rbp
0xa31d33a067		ret	0x18
0xa31d33a06a		call	-0x33406f
0xa31d33a06f		call	-0x33406a
0xa31d33a074		call	-0x334065
...
RelocInfo (size = 6)
0xa31d33a06b  runtime entry  (deoptimization bailout 0)
0xa31d33a070  runtime entry  (deoptimization bailout 1)
0xa31d33a075  runtime entry  (deoptimization bailout 2)

Safepoints (size = 8)

And of course the answer is printed to stdout.

99989998

llv8's People

Contributors

bmeurer avatar mi-ac avatar hashseed avatar vivanishin avatar jeisinger avatar cdai2 avatar verwaest avatar hannespayer avatar ulan avatar arv avatar ripsawridge avatar mtbrandy avatar isheludko avatar dslomov avatar ajklein avatar jaro-sevcik avatar vvaag avatar jakobkummerow avatar weilianglin avatar rossberg avatar caitp avatar jivanh avatar mlippautz avatar wingo avatar rmcilroy avatar marjakh avatar binji avatar mhdawson avatar littledan avatar expatdanno avatar

Watchers

James Cloos avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.