From d1f37af9792b048f7ef98140d067ba129a97c565 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 13 Jan 2014 12:37:34 -0800 Subject: allow relooper to manager its own output buffer, to avoid fixed output limits --- src/relooper/Relooper.cpp | 59 +++++++++++++++++++++++++++++++++++++---------- src/relooper/Relooper.h | 7 +++++- src/relooper/fuzzer.py | 14 +++++++++-- src/relooper/test.cpp | 28 ++++++++++++++++++++++ src/relooper/test.txt | 45 ++++++++++++++++++++++++++++++++++++ tools/shared.py | 2 +- 6 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index 389d7447..1bad872f 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -40,27 +40,56 @@ static void PutIndented(const char *String); static char *OutputBufferRoot = NULL; static char *OutputBuffer = NULL; static int OutputBufferSize = 0; +static int OutputBufferOwned = false; + +static int LeftInOutputBuffer() { + return OutputBufferSize - (OutputBuffer - OutputBufferRoot); +} + +static bool EnsureOutputBuffer(int Needed) { // ensures the output buffer is sufficient. returns true is no problem happened + Needed++; // ensure the trailing \0 is not forgotten + int Left = LeftInOutputBuffer(); + if (!OutputBufferOwned) { + assert(Needed < Left); + } else { + // we own the buffer, and can resize if necessary + if (Needed >= Left) { + int Offset = OutputBuffer - OutputBufferRoot; + int TotalNeeded = OutputBufferSize + Needed - Left + 10240; + int NewSize = OutputBufferSize; + while (NewSize < TotalNeeded) NewSize = NewSize + (NewSize/2); + //printf("resize %d => %d\n", OutputBufferSize, NewSize); + OutputBufferRoot = (char*)realloc(OutputBufferRoot, NewSize); + OutputBuffer = OutputBufferRoot + Offset; + OutputBufferSize = NewSize; + return false; + } + } + return true; +} void PrintIndented(const char *Format, ...) { assert(OutputBuffer); - assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize); + EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION); for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' '; - va_list Args; - va_start(Args, Format); - int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); - int written = vsnprintf(OutputBuffer, left, Format, Args); - assert(written < left); - OutputBuffer += written; - va_end(Args); + int Written; + while (1) { // write and potentially resize buffer until we have enough room + int Left = LeftInOutputBuffer(); + va_list Args; + va_start(Args, Format); + Written = vsnprintf(OutputBuffer, Left, Format, Args); + va_end(Args); + if (EnsureOutputBuffer(Written)) break; + } + OutputBuffer += Written; } void PutIndented(const char *String) { assert(OutputBuffer); - assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize); + EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION); for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' '; - int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot); - int needed = strlen(String)+1; - assert(needed < left); + int Needed = strlen(String)+1; + EnsureOutputBuffer(Needed); strcpy(OutputBuffer, String); OutputBuffer += strlen(String); *OutputBuffer++ = '\n'; @@ -1158,11 +1187,17 @@ void Relooper::Render() { void Relooper::SetOutputBuffer(char *Buffer, int Size) { OutputBufferRoot = OutputBuffer = Buffer; OutputBufferSize = Size; + OutputBufferOwned = false; } void Relooper::MakeOutputBuffer(int Size) { OutputBufferRoot = OutputBuffer = (char*)malloc(Size); OutputBufferSize = Size; + OutputBufferOwned = true; +} + +char *Relooper::GetOutputBuffer() { + return OutputBufferRoot; } void Relooper::SetAsmJSMode(int On) { diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index dfabcabb..6b9394db 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -200,11 +200,16 @@ struct Relooper { void Render(); // Sets the global buffer all printing goes to. Must call this or MakeOutputBuffer. + // XXX: this is deprecated, see MakeOutputBuffer static void SetOutputBuffer(char *Buffer, int Size); - // Creates an output buffer. Must call this or SetOutputBuffer. + // Creates an internal output buffer. Must call this or SetOutputBuffer. Size is + // a hint for the initial size of the buffer, it can be resized later one demand. + // For that reason this is more recommended than SetOutputBuffer. static void MakeOutputBuffer(int Size); + static char *GetOutputBuffer(); + // Sets asm.js mode on or off (default is off) static void SetAsmJSMode(int On); diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py index fa47583e..18db997e 100644 --- a/src/relooper/fuzzer.py +++ b/src/relooper/fuzzer.py @@ -47,8 +47,18 @@ while(1) switch(label) { int main() { char *buffer = (char*)malloc(10*1024*1024); +''' + + if random.randint(0, 1) == 0: + make = False + fast += ''' Relooper::SetOutputBuffer(buffer, 10*1024*1024); ''' + else: + make = True + fast += ''' + Relooper::MakeOutputBuffer(%d); +''' % random.randint(1, 1024*1024*10) for i in range(1, num): slow += ' case %d: print(%d); state = check(); modded = state %% %d\n' % (i, i, len(branches[i])+1) @@ -102,11 +112,11 @@ int main() { printf("\\n\\n"); r.Render(); - puts(buffer); + puts(%s); return 1; } -''' +''' % ('buffer' if not make else 'Relooper::GetOutputBuffer()') slow += '}' diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp index 773f6ee4..b4ce669c 100644 --- a/src/relooper/test.cpp +++ b/src/relooper/test.cpp @@ -286,5 +286,33 @@ int main() { puts(buffer); } + + if (1) { + Relooper::MakeOutputBuffer(10); + + printf("\n\n-- If pattern, emulated, using MakeOutputBuffer --\n\n"); + + Block *b_a = new Block("// block A\n", NULL); + Block *b_b = new Block("// block B\n", "b_check()"); + Block *b_c = new Block("// block C\n", NULL); + + b_a->AddBranchTo(b_b, "check == 10", "atob();"); + b_a->AddBranchTo(b_c, NULL, "atoc();"); + + b_b->AddBranchTo(b_c, "case 17:", "btoc();"); + b_b->AddBranchTo(b_a, NULL, NULL); + + Relooper r; + r.SetEmulate(true); + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + + r.Calculate(b_a); + printf("\n\n", "the_var"); + r.Render(); + + puts(buffer); + } } diff --git a/src/relooper/test.txt b/src/relooper/test.txt index 9bdd4093..cb02b867 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -276,6 +276,51 @@ + label = 1; + L0: while(1) { + switch(label|0) { + case 3: { + // block C + break; + } + case 1: { + // block A + if (check == 10) { + atob(); + label = 2; + continue L0; + } else { + atoc(); + label = 3; + continue L0; + } + break; + } + case 2: { + // block B + switch (b_check()) { + case 17: { + btoc(); + label = 3; + continue L0; + break; + } + default: { + label = 1; + continue L0; + } + } + break; + } + } + } + + + +-- If pattern, emulated, using MakeOutputBuffer -- + + + label = 1; L0: while(1) { switch(label|0) { diff --git a/tools/shared.py b/tools/shared.py index eac4b658..efca1a85 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -345,7 +345,7 @@ def find_temp_directory(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.8.6' +EMSCRIPTEN_VERSION = '1.8.7' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version() -- cgit v1.2.3-18-g5258