Update ReducedFTL
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Nov 2013 18:50:22 +0000 (18:50 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Nov 2013 18:50:22 +0000 (18:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=123805

Reviewed by Sam Weinig.

- Make ReducedFTL build with debug info.

- Give ReducedFTL a --loop mode that runs everything in a loop. Great for finding
  memory leaks and attaching a profiler.

- Reorder the passes so that they match the FTL.

- Make it possible to change the backend opt level and enable the fast isel.

* ReducedFTL/ReducedFTL.c:
(usage):
(roundUpSize):
(mmAllocateCodeSection):
(main):
* ReducedFTL/build.sh:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@158679 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/ReducedFTL/ReducedFTL.c
Tools/ReducedFTL/build.sh

index c2ac14a..dd701bd 100644 (file)
@@ -1,3 +1,26 @@
+2013-11-05  Filip Pizlo  <fpizlo@apple.com>
+
+        Update ReducedFTL
+        https://bugs.webkit.org/show_bug.cgi?id=123805
+
+        Reviewed by Sam Weinig.
+        
+        - Make ReducedFTL build with debug info.
+        
+        - Give ReducedFTL a --loop mode that runs everything in a loop. Great for finding
+          memory leaks and attaching a profiler.
+        
+        - Reorder the passes so that they match the FTL.
+        
+        - Make it possible to change the backend opt level and enable the fast isel.
+
+        * ReducedFTL/ReducedFTL.c:
+        (usage):
+        (roundUpSize):
+        (mmAllocateCodeSection):
+        (main):
+        * ReducedFTL/build.sh:
+
 2013-11-05  Chris Fleizach  <cfleizach@apple.com>
 
         AX: switch DRT AX methods to use nullptr
index 1351fb2..4933b0b 100644 (file)
@@ -62,6 +62,8 @@ static void usage()
     printf("--disassemble    Disassemble all of the generated code at the end.\n");
     printf("--mode <mode>    Set the optimization mode (either \"simple\" or \"opt\").\n");
     printf("--contexts <arg> Set the number of contexts (either \"one\" or \"many\").\n");
+    printf("--loop           Keep recompiling forever. Useful when attaching a profiler.\n");
+    printf("--fast-isel      Enable the \"fast\" instruction selector.\n");
     printf("--help           Print this message.\n");
     printf("\n");
     printf("Unless you specify one of --verbose, --timing, or --disassemble, you will\n");
@@ -84,13 +86,18 @@ struct MemorySection {
 
 static struct MemorySection* sectionHead;
 
-static uint8_t *mmAllocateCodeSection(
-    void *opaqueState, uintptr_t size, unsigned alignment, unsigned sectionID)
+static size_t roundUpSize(size_t size)
 {
     size_t pageSize = getpagesize();
     
+    return (size + pageSize - 1) & ~pageSize;
+}
+
+static uint8_t *mmAllocateCodeSection(
+    void *opaqueState, uintptr_t size, unsigned alignment, unsigned sectionID)
+{
     uint8_t *start = mmap(
-        0, (size + pageSize - 1) & ~pageSize, 
+        0,  roundUpSize(size),
         PROT_WRITE | PROT_READ | PROT_EXEC,
         MAP_ANON | MAP_PRIVATE, -1, 0);
     if (start == (uint8_t*)-1) {
@@ -165,7 +172,11 @@ int main(int c, char **v)
     static int timingFlag = 0;
     static int disassembleFlag = 0;
     bool manyContexts = true;
+    bool loop = false;
     double beforeAll;
+    bool fastIsel = false;
+    int jitOptLevel = 2;
+    struct MemorySection *section;
     
     if (c == 1)
         usage();
@@ -178,6 +189,9 @@ int main(int c, char **v)
             {"disassemble", no_argument, &disassembleFlag, 1},
             {"mode", required_argument, 0, 0},
             {"contexts", required_argument, 0, 0},
+            {"loop", no_argument, 0, 0},
+            {"fast-isel", no_argument, 0, 0},
+            {"jit-opt", required_argument, 0, 0},
             {"help", no_argument, 0, 0}
         };
         
@@ -195,6 +209,10 @@ int main(int c, char **v)
             const char* thisOption = longOptions[optionIndex].name;
             if (!strcmp(thisOption, "help"))
                 usage();
+            if (!strcmp(thisOption, "loop"))
+                loop = true;
+            if (!strcmp(thisOption, "fast-isel"))
+                fastIsel = true;
             if (!strcmp(thisOption, "contexts")) {
                 if (!strcasecmp(optarg, "one"))
                     manyContexts = false;
@@ -206,6 +224,13 @@ int main(int c, char **v)
                 }
                 break;
             }
+            if (!strcmp(thisOption, "jit-opt")) {
+                if (sscanf(optarg, "%d", &jitOptLevel) != 1) {
+                    fprintf(stderr, "Invalid argument for --jit-opt.\n");
+                    exit(1);
+                }
+                break;
+            }
             if (!strcmp(thisOption, "mode")) {
                 mode = strdup(optarg);
                 break;
@@ -232,178 +257,200 @@ int main(int c, char **v)
     filenames = (const char **)(v + optind);
     numFiles = c - optind;
     
-    contexts = malloc(sizeof(LLVMContextRef) * numFiles);
-    modules = malloc(sizeof(LLVMModuleRef) * numFiles);
+    if (!numFiles)
+        return 0;
+    
+    do {
+        contexts = malloc(sizeof(LLVMContextRef) * numFiles);
+        modules = malloc(sizeof(LLVMModuleRef) * numFiles);
     
-    if (manyContexts) {
-        for (i = 0; i < numFiles; ++i)
-            contexts[i] = LLVMContextCreate();
-    } else {
-        LLVMContextRef context = LLVMContextCreate();
-        for (i = 0; i < numFiles; ++i)
-            contexts[i] = context;
-    }
+        if (manyContexts) {
+            for (i = 0; i < numFiles; ++i)
+                contexts[i] = LLVMContextCreate();
+        } else {
+            LLVMContextRef context = LLVMContextCreate();
+            for (i = 0; i < numFiles; ++i)
+                contexts[i] = context;
+        }
     
-    for (i = 0; i < numFiles; ++i) {
-        LLVMMemoryBufferRef buffer;
-        const char* filename = filenames[i];
+        for (i = 0; i < numFiles; ++i) {
+            LLVMMemoryBufferRef buffer;
+            const char* filename = filenames[i];
         
-        if (LLVMCreateMemoryBufferWithContentsOfFile(filename, &buffer, &error)) {
-            fprintf(stderr, "Error reading file %s: %s\n", filename, error);
-            exit(1);
-        }
+            if (LLVMCreateMemoryBufferWithContentsOfFile(filename, &buffer, &error)) {
+                fprintf(stderr, "Error reading file %s: %s\n", filename, error);
+                exit(1);
+            }
         
-        if (LLVMParseBitcodeInContext(contexts[i], buffer, modules + i, &error)) {
-            fprintf(stderr, "Error parsing file %s: %s\n", filename, error);
-            exit(1);
-        }
+            if (LLVMParseBitcodeInContext(contexts[i], buffer, modules + i, &error)) {
+                fprintf(stderr, "Error parsing file %s: %s\n", filename, error);
+                exit(1);
+            }
         
-        LLVMDisposeMemoryBuffer(buffer);
+            LLVMDisposeMemoryBuffer(buffer);
         
-        if (verboseFlag) {
-            printf("Module #%u (%s) after parsing:\n", i, filename);
-            LLVMDumpModule(modules[i]);
+            if (verboseFlag) {
+                printf("Module #%u (%s) after parsing:\n", i, filename);
+                LLVMDumpModule(modules[i]);
+            }
         }
-    }
 
-    if (verboseFlag)
-        printf("Generating code for modules...\n");
+        if (verboseFlag)
+            printf("Generating code for modules...\n");
     
-    if (timingFlag)
-        beforeAll = currentTime();
-    for (i = 0; i < numFiles; ++i) {
-        LLVMModuleRef module;
-        LLVMExecutionEngineRef engine;
-        struct LLVMMCJITCompilerOptions options;
-        LLVMValueRef value;
-        LLVMPassManagerRef functionPasses = 0;
-        LLVMPassManagerRef modulePasses = 0;
+        if (timingFlag)
+            beforeAll = currentTime();
+        for (i = 0; i < numFiles; ++i) {
+            LLVMModuleRef module;
+            LLVMExecutionEngineRef engine;
+            struct LLVMMCJITCompilerOptions options;
+            LLVMValueRef value;
+            LLVMPassManagerRef functionPasses = 0;
+            LLVMPassManagerRef modulePasses = 0;
         
-        double before;
+            double before;
         
-        if (timingFlag)
-            before = currentTime();
+            if (timingFlag)
+                before = currentTime();
         
-        module = modules[i];
+            module = modules[i];
 
-        LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
-        options.OptLevel = 2;
-        options.EnableFastISel = 0;
-        options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
-            0, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy);
+            LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
+            options.OptLevel = jitOptLevel;
+            options.EnableFastISel = fastIsel;
+            options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
+                0, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy);
     
-        if (LLVMCreateMCJITCompilerForModule(&engine, module, &options, sizeof(options), &error)) {
-            fprintf(stderr, "Error building MCJIT: %s\n", error);
-            exit(1);
-        }
+            if (LLVMCreateMCJITCompilerForModule(&engine, module, &options, sizeof(options), &error)) {
+                fprintf(stderr, "Error building MCJIT: %s\n", error);
+                exit(1);
+            }
     
-        if (!strcasecmp(mode, "simple")) {
-            modulePasses = LLVMCreatePassManager();
-            LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
-            LLVMAddConstantPropagationPass(modulePasses);
-            LLVMAddInstructionCombiningPass(modulePasses);
-            LLVMAddPromoteMemoryToRegisterPass(modulePasses);
-            LLVMAddBasicAliasAnalysisPass(modulePasses);
-            LLVMAddTypeBasedAliasAnalysisPass(modulePasses);
-            LLVMAddGVNPass(modulePasses);
-            LLVMAddCFGSimplificationPass(modulePasses);
-            LLVMRunPassManager(modulePasses, module);
-        } else if (!strcasecmp(mode, "opt")) {
-            LLVMPassManagerBuilderRef passBuilder;
+            if (!strcasecmp(mode, "simple")) {
+                modulePasses = LLVMCreatePassManager();
+                LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
+                LLVMAddPromoteMemoryToRegisterPass(modulePasses);
+                LLVMAddConstantPropagationPass(modulePasses);
+                LLVMAddInstructionCombiningPass(modulePasses);
+                LLVMAddBasicAliasAnalysisPass(modulePasses);
+                LLVMAddTypeBasedAliasAnalysisPass(modulePasses);
+                LLVMAddGVNPass(modulePasses);
+                LLVMAddCFGSimplificationPass(modulePasses);
+                LLVMRunPassManager(modulePasses, module);
+            } else if (!strcasecmp(mode, "opt")) {
+                LLVMPassManagerBuilderRef passBuilder;
 
-            passBuilder = LLVMPassManagerBuilderCreate();
-            LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
-            LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
+                passBuilder = LLVMPassManagerBuilderCreate();
+                LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
+                LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
         
-            functionPasses = LLVMCreateFunctionPassManagerForModule(module);
-            modulePasses = LLVMCreatePassManager();
+                functionPasses = LLVMCreateFunctionPassManagerForModule(module);
+                modulePasses = LLVMCreatePassManager();
         
-            LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
+                LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses);
         
-            LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses);
-            LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
+                LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses);
+                LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
         
-            LLVMPassManagerBuilderDispose(passBuilder);
+                LLVMPassManagerBuilderDispose(passBuilder);
         
-            LLVMInitializeFunctionPassManager(functionPasses);
-            for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value))
-                LLVMRunFunctionPassManager(functionPasses, value);
-            LLVMFinalizeFunctionPassManager(functionPasses);
+                LLVMInitializeFunctionPassManager(functionPasses);
+                for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value))
+                    LLVMRunFunctionPassManager(functionPasses, value);
+                LLVMFinalizeFunctionPassManager(functionPasses);
         
-            LLVMRunPassManager(modulePasses, module);
-        } else {
-            fprintf(stderr, "Bad optimization mode: %s.\n", mode);
-            fprintf(stderr, "Valid modes are: \"simple\" or \"opt\".\n");
-            exit(1);
-        }
+                LLVMRunPassManager(modulePasses, module);
+            } else {
+                fprintf(stderr, "Bad optimization mode: %s.\n", mode);
+                fprintf(stderr, "Valid modes are: \"simple\" or \"opt\".\n");
+                exit(1);
+            }
 
-        if (verboseFlag) {
-            printf("Module #%d (%s) after optimization:\n", i, filenames[i]);
-            LLVMDumpModule(module);
-        }
+            if (verboseFlag) {
+                printf("Module #%d (%s) after optimization:\n", i, filenames[i]);
+                LLVMDumpModule(module);
+            }
     
-        for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) {
-            if (LLVMIsDeclaration(value))
-                continue;
-            LLVMGetPointerToGlobal(engine, value);
-        }
+            for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) {
+                if (LLVMIsDeclaration(value))
+                    continue;
+                LLVMGetPointerToGlobal(engine, value);
+            }
 
-        if (functionPasses)
-            LLVMDisposePassManager(functionPasses);
-        if (modulePasses)
-            LLVMDisposePassManager(modulePasses);
+            if (functionPasses)
+                LLVMDisposePassManager(functionPasses);
+            if (modulePasses)
+                LLVMDisposePassManager(modulePasses);
     
-        LLVMDisposeExecutionEngine(engine);
+            LLVMDisposeExecutionEngine(engine);
+        
+            if (timingFlag) {
+                double after = currentTime();
+                printf("Module #%d (%s) took %lf ms.\n", i, filenames[i], (after - before) * 1000);
+            }
+        }
+
+        if (manyContexts) {
+            for (i = 0; i < numFiles; ++i)
+                LLVMContextDispose(contexts[i]);
+        } else
+            LLVMContextDispose(contexts[0]);
         
         if (timingFlag) {
             double after = currentTime();
-            printf("Module #%d (%s) took %lf ms.\n", i, filenames[i], (after - before) * 1000);
+            printf("Compilation took a total of %lf ms.\n", (after - beforeAll) * 1000);
         }
-    }
-    if (timingFlag) {
-        double after = currentTime();
-        printf("Compilation took a total of %lf ms.\n", (after - beforeAll) * 1000);
-    }
     
-    if (disassembleFlag) {
-        LLVMDisasmContextRef disassembler;
-        struct MemorySection *section;
+        if (disassembleFlag) {
+            LLVMDisasmContextRef disassembler;
         
-        disassembler = LLVMCreateDisasm("x86_64-apple-darwin", 0, 0, 0, symbolLookupCallback);
-        if (!disassembler) {
-            fprintf(stderr, "Error building disassembler.\n");
-            exit(1);
-        }
+            disassembler = LLVMCreateDisasm("x86_64-apple-darwin", 0, 0, 0, symbolLookupCallback);
+            if (!disassembler) {
+                fprintf(stderr, "Error building disassembler.\n");
+                exit(1);
+            }
     
-        for (section = sectionHead; section; section = section->next) {
-            printf("Disassembly for section %p:\n", section);
+            for (section = sectionHead; section; section = section->next) {
+                printf("Disassembly for section %p:\n", section);
         
-            char pcString[20];
-            char instructionString[1000];
-            uint8_t *pc;
-            uint8_t *end;
+                char pcString[20];
+                char instructionString[1000];
+                uint8_t *pc;
+                uint8_t *end;
         
-            pc = section->start;
-            end = pc + section->size;
+                pc = section->start;
+                end = pc + section->size;
         
-            while (pc < end) {
-                snprintf(
-                    pcString, sizeof(pcString), "0x%lx",
-                    (unsigned long)(uintptr_t)pc);
+                while (pc < end) {
+                    snprintf(
+                        pcString, sizeof(pcString), "0x%lx",
+                        (unsigned long)(uintptr_t)pc);
             
-                size_t instructionSize = LLVMDisasmInstruction(
-                    disassembler, pc, end - pc, (uintptr_t)pc,
-                    instructionString, sizeof(instructionString));
+                    size_t instructionSize = LLVMDisasmInstruction(
+                        disassembler, pc, end - pc, (uintptr_t)pc,
+                        instructionString, sizeof(instructionString));
             
-                if (!instructionSize)
-                    snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++);
-                else
-                    pc += instructionSize;
+                    if (!instructionSize)
+                        snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++);
+                    else
+                        pc += instructionSize;
             
-                printf("    %16s: %s\n", pcString, instructionString);
+                    printf("    %16s: %s\n", pcString, instructionString);
+                }
             }
         }
-    }
+        
+        for (section = sectionHead; section;) {
+            struct MemorySection* nextSection = section->next;
+            
+            munmap(section->start, roundUpSize(section->size));
+            free(section);
+            
+            section = nextSection;
+        }
+        sectionHead = 0;
+        
+    } while (loop);
     
     return 0;
 }
index 084dd8e..c8c5528 100755 (executable)
@@ -10,5 +10,5 @@ else
     configPath="${LLVM_PATH}/bin/llvm-config"
 fi
 
-clang -c -o ReducedFTL.o ReducedFTL.c `${configPath} --cppflags --cflags`
+clang -c -o ReducedFTL.o ReducedFTL.c `${configPath} --cppflags --cflags` -g
 clang++ -o ReducedFTL ReducedFTL.o -stdlib=libc++ `${configPath} --ldflags --libs` -lcurses