[JavaScriptCore] Fix FTL on platform EFL.
authorllango.u-szeged@partner.samsung.com <llango.u-szeged@partner.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Sep 2014 08:52:22 +0000 (08:52 +0000)
committerllango.u-szeged@partner.samsung.com <llango.u-szeged@partner.samsung.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 11 Sep 2014 08:52:22 +0000 (08:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=133571

Reviewed by Filip Pizlo.

.:

Revert r169181.

* Source/cmake/FindLIBCXXABI.cmake: Removed.
* Source/cmake/OptionsEfl.cmake:

Source/JavaScriptCore:

There are no compact_unwind sections on Linux systems so FTL crashes.
We have to parse eh_frame in FTLUnwindInfo instead of compact_unwind
and get the information for stack unwinding from there.

* CMakeLists.txt: Revert r169181.
* ftl/FTLCompile.cpp:
Change section name literals to use SECTION_NAME macro, because of architecture differencies.
(JSC::FTL::mmAllocateCodeSection):
(JSC::FTL::mmAllocateDataSection):
(JSC::FTL::compile):
* ftl/FTLJITCode.h:
We need the SECTION_NAME macro in FTLCompile and FTLLink, so we define it here.
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLState.h:
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLUnwindInfo.h:
* ftl/FTLUnwindInfo.cpp:
Lift the eh_frame parsing method from LLVM/libcxxabi project and modify it for our purposes.
Parse eh_frame on Linux instead of compact_unwind.
(JSC::FTL::UnwindInfo::parse):

Tools:

* efl/install-dependencies: Revert r169181.
* efl/jhbuild.modules: Clone and build a custom branch.
This branch contains some fix for FTL of platform EFL.
The branch is a fork of llvm r206311.

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

15 files changed:
ChangeLog
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/ftl/FTLCompile.cpp
Source/JavaScriptCore/ftl/FTLJITCode.h
Source/JavaScriptCore/ftl/FTLLink.cpp
Source/JavaScriptCore/ftl/FTLState.cpp
Source/JavaScriptCore/ftl/FTLState.h
Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp
Source/JavaScriptCore/ftl/FTLUnwindInfo.h
Source/cmake/FindLIBCXXABI.cmake [deleted file]
Source/cmake/OptionsEfl.cmake
Tools/ChangeLog
Tools/efl/install-dependencies
Tools/efl/jhbuild.modules

index eaea9fc..f600352 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-09-11  László Langó  <llango.u-szeged@partner.samsung.com>
+
+        [JavaScriptCore] Fix FTL on platform EFL.
+        https://bugs.webkit.org/show_bug.cgi?id=133571
+
+        Reviewed by Filip Pizlo.
+
+        Revert r169181.
+
+        * Source/cmake/FindLIBCXXABI.cmake: Removed.
+        * Source/cmake/OptionsEfl.cmake:
+
 2014-09-08  Eva Balazsfalvi  <evab.u-szeged@partner.samsung.com>
 
         Remove FILTERS flag
index 6ba82ef..c5fd621 100644 (file)
@@ -753,7 +753,6 @@ if (ENABLE_FTL_JIT)
     # Added extra items for JavaScriptCore
     list(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
         ${LLVM_INCLUDE_DIRS}
-        ${LIBCXXABI_INCLUDE_DIRS}
     )
 
     list(APPEND JavaScriptCore_SOURCES
index 405cce5..af48f31 100644 (file)
@@ -1,3 +1,33 @@
+2014-09-11  László Langó  <llango.u-szeged@partner.samsung.com>
+
+        [JavaScriptCore] Fix FTL on platform EFL.
+        https://bugs.webkit.org/show_bug.cgi?id=133571
+
+        Reviewed by Filip Pizlo.
+
+        There are no compact_unwind sections on Linux systems so FTL crashes.
+        We have to parse eh_frame in FTLUnwindInfo instead of compact_unwind
+        and get the information for stack unwinding from there.
+
+        * CMakeLists.txt: Revert r169181.
+        * ftl/FTLCompile.cpp:
+        Change section name literals to use SECTION_NAME macro, because of architecture differencies.
+        (JSC::FTL::mmAllocateCodeSection):
+        (JSC::FTL::mmAllocateDataSection):
+        (JSC::FTL::compile):
+        * ftl/FTLJITCode.h:
+        We need the SECTION_NAME macro in FTLCompile and FTLLink, so we define it here.
+        * ftl/FTLLink.cpp:
+        (JSC::FTL::link):
+        * ftl/FTLState.h:
+        * ftl/FTLState.cpp:
+        (JSC::FTL::State::State):
+        * ftl/FTLUnwindInfo.h:
+        * ftl/FTLUnwindInfo.cpp:
+        Lift the eh_frame parsing method from LLVM/libcxxabi project and modify it for our purposes.
+        Parse eh_frame on Linux instead of compact_unwind.
+        (JSC::FTL::UnwindInfo::parse):
+
 2014-09-10  Saam Barati  <saambarati1@gmail.com>
 
         Web Inspector: Modify the type profiler runtime protocol to transfer some computation into the WebInspector
index 10c4cfe..26a7bc5 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Samsung Electronics
+ * Copyright (C) 2014 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -61,9 +63,9 @@ static uint8_t* mmAllocateCodeSection(
     
     // LLVM used to put __compact_unwind in a code section. We keep this here defensively,
     // for clients that use older LLVMs.
-    if (!strcmp(sectionName, "__compact_unwind")) {
-        state.compactUnwind = result->start();
-        state.compactUnwindSize = result->sizeInBytes();
+    if (!strcmp(sectionName, SECTION_NAME("compact_unwind"))) {
+        state.unwindDataSection = result->start();
+        state.unwindDataSectionSize = result->sizeInBytes();
     }
     
     state.jitCode->addHandle(result);
@@ -80,21 +82,25 @@ static uint8_t* mmAllocateDataSection(
     UNUSED_PARAM(isReadOnly);
 
     // Allocate the GOT in the code section to make it reachable for all code.
-    if (!strcmp(sectionName, "__got"))
+    if (!strcmp(sectionName, SECTION_NAME("got")))
         return mmAllocateCodeSection(opaqueState, size, alignment, sectionID, sectionName);
 
     State& state = *static_cast<State*>(opaqueState);
 
     RefPtr<DataSection> section = adoptRef(new DataSection(size, alignment));
 
-    if (!strcmp(sectionName, "__llvm_stackmaps"))
+    if (!strcmp(sectionName, SECTION_NAME("llvm_stackmaps")))
         state.stackmapsSection = section;
     else {
         state.jitCode->addDataSection(section);
         state.dataSectionNames.append(sectionName);
-        if (!strcmp(sectionName, "__compact_unwind")) {
-            state.compactUnwind = section->base();
-            state.compactUnwindSize = size;
+#if OS(DARWIN)
+        if (!strcmp(sectionName, SECTION_NAME("compact_unwind"))) {
+#elif OS(LINUX)
+        if (!strcmp(sectionName, SECTION_NAME("eh_frame"))) {
+#endif
+            state.unwindDataSection = section->base();
+            state.unwindDataSectionSize = size;
         }
     }
 
@@ -717,7 +723,8 @@ void compile(State& state, Safepoint::Result& safepointResult)
     }
     
     bool didSeeUnwindInfo = state.jitCode->unwindInfo.parse(
-        state.compactUnwind, state.compactUnwindSize, state.generatedFunction);
+        state.unwindDataSection, state.unwindDataSectionSize,
+        state.generatedFunction);
     if (shouldShowDisassembly()) {
         dataLog("Unwind info for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n");
         if (didSeeUnwindInfo)
@@ -751,7 +758,7 @@ void compile(State& state, Safepoint::Result& safepointResult)
         
         if (shouldShowDisassembly()) {
             for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) {
-                if (state.codeSectionNames[i] != "__text")
+                if (state.codeSectionNames[i] != SECTION_NAME("text"))
                     continue;
                 
                 ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get();
index 9894d4c..6f6838f 100644 (file)
 #include "LLVMAPI.h"
 #include <wtf/RefCountedArray.h>
 
+#if OS(DARWIN)
+#define SECTION_NAME_PREFIX "__"
+#elif OS(LINUX)
+#define SECTION_NAME_PREFIX "."
+#else
+#error "Unsupported platform"
+#endif
+
+#define SECTION_NAME(NAME) (SECTION_NAME_PREFIX NAME)
+
 namespace JSC { namespace FTL {
 
 class JITCode : public JSC::JITCode {
index 71b9698..d9f4697 100644 (file)
@@ -128,7 +128,7 @@ void link(State& state)
         
         out.print("    Disassembly:\n");
         for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) {
-            if (state.codeSectionNames[i] != "__text")
+            if (state.codeSectionNames[i] != SECTION_NAME("text"))
                 continue;
             
                 ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get();
index 0b5fd64..265cec7 100644 (file)
@@ -49,8 +49,8 @@ State::State(Graph& graph)
     , module(0)
     , function(0)
     , generatedFunction(0)
-    , compactUnwind(0)
-    , compactUnwindSize(0)
+    , unwindDataSection(0)
+    , unwindDataSectionSize(0)
 {
 
 #if ENABLE(FTL_NATIVE_CALL_INLINING)
index 8662d63..e986517 100644 (file)
@@ -77,8 +77,8 @@ public:
     Vector<JSCall> jsCalls;
     Vector<CString> codeSectionNames;
     Vector<CString> dataSectionNames;
-    void* compactUnwind;
-    size_t compactUnwindSize;
+    void* unwindDataSection;
+    size_t unwindDataSectionSize;
     RefPtr<DataSection> stackmapsSection;
     
     void dumpState(const char* when);
index 98c1831..c59d44f 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Samsung Electronics
+ * Copyright (C) 2014 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ==============================================================================
+ *
+ * University of Illinois/NCSA
+ * Open Source License
+ *
+ * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
+ *
+ * All rights reserved.
+ *
+ * Developed by:
+ *
+ *    LLVM Team
+ *
+ *    University of Illinois at Urbana-Champaign
+ *
+ *    http://llvm.org
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal with
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ *    * Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimers.
+ *
+ *    * Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimers in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ *    * Neither the names of the LLVM Team, University of Illinois at
+ *      Urbana-Champaign, nor the names of its contributors may be used to
+ *      endorse or promote products derived from this Software without specific
+ *      prior written permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+ * SOFTWARE.
+ *
+ * ==============================================================================
+ *
+ * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
  */
 
 #include "config.h"
@@ -28,7 +96,9 @@
 
 #if ENABLE(FTL_JIT)
 
+#if OS(DARWIN)
 #include <mach-o/compact_unwind_encoding.h>
+#endif
 #include <wtf/ListDump.h>
 
 namespace JSC { namespace FTL {
@@ -36,8 +106,9 @@ namespace JSC { namespace FTL {
 UnwindInfo::UnwindInfo() { }
 UnwindInfo::~UnwindInfo() { }
 
-namespace {
 
+namespace {
+#if OS(DARWIN)
 struct CompactUnwind {
     void* function;
     uint32_t size;
@@ -45,17 +116,479 @@ struct CompactUnwind {
     void* personality;
     void* lsda;
 };
+#elif OS(LINUX)
+// DWARF unwind instructions
+enum {
+    DW_CFA_nop                 = 0x0,
+    DW_CFA_set_loc             = 0x1,
+    DW_CFA_advance_loc1        = 0x2,
+    DW_CFA_advance_loc2        = 0x3,
+    DW_CFA_advance_loc4        = 0x4,
+    DW_CFA_offset_extended     = 0x5,
+    DW_CFA_def_cfa             = 0xC,
+    DW_CFA_def_cfa_register    = 0xD,
+    DW_CFA_def_cfa_offset      = 0xE,
+    DW_CFA_offset_extended_sf = 0x11,
+    DW_CFA_def_cfa_sf         = 0x12,
+    DW_CFA_def_cfa_offset_sf  = 0x13,
+    // high 2 bits are 0x1, lower 6 bits are delta
+    DW_CFA_advance_loc        = 0x40,
+    // high 2 bits are 0x2, lower 6 bits are register
+    DW_CFA_offset             = 0x80
+};
+
+enum {
+    DW_CFA_operand_mask = 0x3F // low 6 bits mask for opcode-encoded operands in DW_CFA_advance_loc and DW_CFA_offset
+};
+
+// FSF exception handling Pointer-Encoding constants
+enum {
+    DW_EH_PE_ptr       = 0x00,
+    DW_EH_PE_uleb128   = 0x01,
+    DW_EH_PE_udata2    = 0x02,
+    DW_EH_PE_udata4    = 0x03,
+    DW_EH_PE_udata8    = 0x04,
+    DW_EH_PE_sleb128   = 0x09,
+    DW_EH_PE_sdata2    = 0x0A,
+    DW_EH_PE_sdata4    = 0x0B,
+    DW_EH_PE_sdata8    = 0x0C,
+    DW_EH_PE_absptr    = 0x00,
+    DW_EH_PE_pcrel     = 0x10,
+    DW_EH_PE_indirect  = 0x80
+};
+
+enum {
+    DW_EH_PE_relative_mask = 0x70
+};
+
+// 64-bit x86_64 registers
+enum {
+    UNW_X86_64_rbx =  3,
+    UNW_X86_64_rbp =  6,
+    UNW_X86_64_r12 = 12,
+    UNW_X86_64_r13 = 13,
+    UNW_X86_64_r14 = 14,
+    UNW_X86_64_r15 = 15
+};
+
+enum {
+    DW_X86_64_RET_addr = 16
+};
+
+static uint8_t get8(uintptr_t addr)    { return *((uint8_t*)addr); }
+static uint16_t get16(uintptr_t addr)  { return *((uint16_t*)addr); }
+static uint32_t get32(uintptr_t addr)  { return *((uint32_t*)addr); }
+static uint64_t get64(uintptr_t addr)  { return *((uint64_t*)addr); }
+
+static uintptr_t getP(uintptr_t addr)
+{
+    // FIXME: add support for 32 bit pointers on 32 bit architectures
+    return get64(addr);
+}
+
+static uint64_t getULEB128(uintptr_t& addr, uintptr_t end)
+{
+    const uint8_t* p = (uint8_t*)addr;
+    const uint8_t* pend = (uint8_t*)end;
+    uint64_t result = 0;
+    int bit = 0;
+    do  {
+        uint64_t b;
+
+        RELEASE_ASSERT(p != pend); // truncated uleb128 expression
+
+        b = *p & 0x7f;
+
+        RELEASE_ASSERT(!(bit >= 64 || b << bit >> bit != b)); // malformed uleb128 expression
+
+        result |= b << bit;
+        bit += 7;
+    } while (*p++ >= 0x80);
+    addr = (uintptr_t)p;
+    return result;
+}
+
+static int64_t getSLEB128(uintptr_t& addr, uintptr_t end)
+{
+    const uint8_t* p = (uint8_t*)addr;
+    const uint8_t* pend = (uint8_t*)end;
+
+    int64_t result = 0;
+    int bit = 0;
+    uint8_t byte;
+    do {
+        RELEASE_ASSERT(p != pend); // truncated sleb128 expression
+
+        byte = *p++;
+        result |= ((byte & 0x7f) << bit);
+        bit += 7;
+    } while (byte & 0x80);
+    // sign extend negative numbers
+    if ((byte & 0x40))
+        result |= (-1LL) << bit;
+    addr = (uintptr_t)p;
+    return result;
+}
+
+static uintptr_t getEncodedP(uintptr_t& addr, uintptr_t end, uint8_t encoding)
+{
+    uintptr_t startAddr = addr;
+    const uint8_t* p = (uint8_t*)addr;
+    uintptr_t result;
+
+    // first get value
+    switch (encoding & 0x0F) {
+    case DW_EH_PE_ptr:
+        result = getP(addr);
+        p += sizeof(uintptr_t);
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_uleb128:
+        result = getULEB128(addr, end);
+        break;
+    case DW_EH_PE_udata2:
+        result = get16(addr);
+        p += 2;
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_udata4:
+        result = get32(addr);
+        p += 4;
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_udata8:
+        result = get64(addr);
+        p += 8;
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_sleb128:
+        result = getSLEB128(addr, end);
+        break;
+    case DW_EH_PE_sdata2:
+        result = (int16_t)get16(addr);
+        p += 2;
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_sdata4:
+        result = (int32_t)get32(addr);
+        p += 4;
+        addr = (uintptr_t)p;
+        break;
+    case DW_EH_PE_sdata8:
+        result = get64(addr);
+        p += 8;
+        addr = (uintptr_t)p;
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED(); // unknown pointer encoding
+    }
+
+    // then add relative offset
+    switch (encoding & DW_EH_PE_relative_mask) {
+    case DW_EH_PE_absptr:
+        // do nothing
+        break;
+    case DW_EH_PE_pcrel:
+        result += startAddr;
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED(); // unsupported or unknown pointer encoding
+    }
+
+    if (encoding & DW_EH_PE_indirect)
+        result = getP(result);
+
+    return result;
+}
+
+// Information encoded in a CIE (Common Information Entry)
+struct CIE_Info {
+    uintptr_t cieStart;
+    uintptr_t cieLength;
+    uintptr_t cieInstructions;
+    uint8_t pointerEncoding;
+    uint8_t lsdaEncoding;
+    uint8_t personalityEncoding;
+    uint8_t personalityOffsetInCIE;
+    uintptr_t personality;
+    int dataAlignFactor;
+    bool fdesHaveAugmentationData;
+};
+
+// Information about an FDE (Frame Description Entry)
+struct FDE_Info {
+    uintptr_t fdeStart;
+    uintptr_t fdeLength;
+    uintptr_t fdeInstructions;
+    uintptr_t lsda;
+};
+
+// Information about a frame layout and registers saved determined
+// by "running" the dwarf FDE "instructions"
+enum { MaxRegisterNumber = 17 };
+
+struct RegisterLocation {
+    bool saved;
+    int64_t offset;
+};
+
+struct PrologInfo {
+    uint32_t cfaRegister;
+    int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
+    RegisterLocation savedRegisters[MaxRegisterNumber]; // from where to restore registers
+};
+
+static void parseCIE(uintptr_t cie, CIE_Info* cieInfo)
+{
+    cieInfo->pointerEncoding = 0;
+    cieInfo->lsdaEncoding = 0;
+    cieInfo->personalityEncoding = 0;
+    cieInfo->personalityOffsetInCIE = 0;
+    cieInfo->personality = 0;
+    cieInfo->dataAlignFactor = 0;
+    cieInfo->fdesHaveAugmentationData = false;
+    cieInfo->cieStart = cie;
+
+    uintptr_t p = cie;
+    uint64_t cieLength = get32(p);
+    p += 4;
+    uintptr_t cieContentEnd = p + cieLength;
+    if (cieLength == 0xffffffff) {
+        // 0xffffffff means length is really next 8 bytes
+        cieLength = get64(p);
+        p += 8;
+        cieContentEnd = p + cieLength;
+    }
 
+    RELEASE_ASSERT(cieLength);
+
+    // CIE ID is always 0
+    RELEASE_ASSERT(!get32(p)); // CIE ID is not zero
+    p += 4;
+    // Version is always 1 or 3
+    uint8_t version = get8(p);
+    RELEASE_ASSERT((version == 1) || (version == 3)); // CIE version is not 1 or 3
+
+    ++p;
+    // save start of augmentation string and find end
+    uintptr_t strStart = p;
+    while (get8(p))
+        ++p;
+    ++p;
+    // parse code aligment factor
+    getULEB128(p, cieContentEnd);
+    // parse data alignment factor
+    cieInfo->dataAlignFactor = getSLEB128(p, cieContentEnd);
+    // parse return address register
+    getULEB128(p, cieContentEnd);
+    // parse augmentation data based on augmentation string
+    if (get8(strStart) == 'z') {
+        // parse augmentation data length
+        getULEB128(p, cieContentEnd);
+        for (uintptr_t s = strStart; get8(s) != '\0'; ++s) {
+            switch (get8(s)) {
+            case 'z':
+                cieInfo->fdesHaveAugmentationData = true;
+                break;
+            case 'P': // FIXME: should assert on personality (just to keep in sync with the CU behaviour)
+                cieInfo->personalityEncoding = get8(p);
+                ++p;
+                cieInfo->personalityOffsetInCIE = p - cie;
+                cieInfo->personality = getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
+                break;
+            case 'L': // FIXME: should assert on LSDA (just to keep in sync with the CU behaviour)
+                cieInfo->lsdaEncoding = get8(p);
+                ++p;
+                break;
+            case 'R':
+                cieInfo->pointerEncoding = get8(p);
+                ++p;
+                break;
+            default:
+                // ignore unknown letters
+                break;
+            }
+        }
+    }
+    cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
+    cieInfo->cieInstructions = p;
+}
+
+static void findFDE(uintptr_t pc, uintptr_t ehSectionStart, uint32_t sectionLength, FDE_Info* fdeInfo, CIE_Info* cieInfo)
+{
+    uintptr_t p = ehSectionStart;
+    const uintptr_t ehSectionEnd = p + sectionLength;
+    while (p < ehSectionEnd) {
+        uintptr_t currentCFI = p;
+        uint64_t cfiLength = get32(p);
+        p += 4;
+        if (cfiLength == 0xffffffff) {
+            // 0xffffffff means length is really next 8 bytes
+            cfiLength = get64(p);
+            p += 8;
+        }
+        RELEASE_ASSERT(cfiLength); // end marker reached before finding FDE for pc
+
+        uint32_t id = get32(p);
+        if (!id) {
+            // skip over CIEs
+            p += cfiLength;
+        } else {
+            // process FDE to see if it covers pc
+            uintptr_t nextCFI = p + cfiLength;
+            uint32_t ciePointer = get32(p);
+            uintptr_t cieStart = p - ciePointer;
+            // validate pointer to CIE is within section
+            RELEASE_ASSERT((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)); // malformed FDE. CIE is bad
+
+            parseCIE(cieStart, cieInfo);
+
+            p += 4;
+            // parse pc begin and range
+            uintptr_t pcStart = getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
+            uintptr_t pcRange = getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
+
+            // test if pc is within the function this FDE covers
+            // if pc is not in begin/range, skip this FDE
+            if ((pcStart <= pc) && (pc < pcStart+pcRange)) {
+                // parse rest of info
+                fdeInfo->lsda = 0;
+                // check for augmentation length
+                if (cieInfo->fdesHaveAugmentationData) {
+                    uintptr_t augLen = getULEB128(p, nextCFI);
+                    uintptr_t endOfAug = p + augLen;
+                    if (cieInfo->lsdaEncoding) {
+                        // peek at value (without indirection). Zero means no lsda
+                        uintptr_t lsdaStart = p;
+                        if (getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F)) {
+                            // reset pointer and re-parse lsda address
+                            p = lsdaStart;
+                            fdeInfo->lsda = getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
+                        }
+                    }
+                    p = endOfAug;
+                }
+                fdeInfo->fdeStart = currentCFI;
+                fdeInfo->fdeLength = nextCFI - currentCFI;
+                fdeInfo->fdeInstructions = p;
+
+                return; // FDE found
+            }
+
+            p = nextCFI;
+        }
+    }
+
+    RELEASE_ASSERT_NOT_REACHED(); // no FDE found for pc
+}
+
+static void executeDefCFARegister(uint64_t reg, PrologInfo* results)
+{
+    RELEASE_ASSERT(reg <= MaxRegisterNumber); // reg too big
+    results->cfaRegister = reg;
+}
+
+static void executeDefCFAOffset(int64_t offset, PrologInfo* results)
+{
+    RELEASE_ASSERT(offset <= 0x80000000); // cfa has negative offset (dwarf might contain epilog)
+    results->cfaRegisterOffset = offset;
+}
+
+static void executeOffset(uint64_t reg, int64_t offset, PrologInfo *results)
+{
+    if (reg > MaxRegisterNumber)
+        return;
+
+    RELEASE_ASSERT(!results->savedRegisters[reg].saved);
+    results->savedRegisters[reg].saved = true;
+    results->savedRegisters[reg].offset = offset;
+}
+
+static void parseInstructions(uintptr_t instructions, uintptr_t instructionsEnd, const CIE_Info& cieInfo, PrologInfo* results)
+{
+    uintptr_t p = instructions;
+
+    // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
+    while ((p < instructionsEnd)) {
+        uint64_t reg;
+        uint8_t opcode = get8(p);
+        uint8_t operand;
+        ++p;
+        switch (opcode) {
+        case DW_CFA_nop:
+            break;
+        case DW_CFA_set_loc:
+            getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
+            break;
+        case DW_CFA_advance_loc1:
+            p += 1;
+            break;
+        case DW_CFA_advance_loc2:
+            p += 2;
+            break;
+        case DW_CFA_advance_loc4:
+            p += 4;
+            break;
+        case DW_CFA_def_cfa:
+            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
+            executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
+            break;
+        case DW_CFA_def_cfa_sf:
+            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
+            executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
+            break;
+        case DW_CFA_def_cfa_register:
+            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
+            break;
+        case DW_CFA_def_cfa_offset:
+            executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
+            break;
+        case DW_CFA_def_cfa_offset_sf:
+            executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
+            break;
+        case DW_CFA_offset_extended:
+            reg = getULEB128(p, instructionsEnd);
+            executeOffset(reg, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
+            break;
+        case DW_CFA_offset_extended_sf:
+            reg = getULEB128(p, instructionsEnd);
+            executeOffset(reg, getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
+            break;
+        default:
+            operand = opcode & DW_CFA_operand_mask;
+            switch (opcode & ~DW_CFA_operand_mask) {
+            case DW_CFA_offset:
+                executeOffset(operand, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
+                break;
+            case DW_CFA_advance_loc:
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED(); // unknown or unsupported CFA opcode
+            }
+        }
+    }
+}
+
+static void parseFDEInstructions(const FDE_Info& fdeInfo, const CIE_Info& cieInfo, PrologInfo* results)
+{
+    // clear results
+    bzero(results, sizeof(PrologInfo));
+
+    // parse CIE then FDE instructions
+    parseInstructions(cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, cieInfo, results);
+    parseInstructions(fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, results);
+}
+#endif
 } // anonymous namespace
 
 bool UnwindInfo::parse(void* section, size_t size, GeneratedFunction generatedFunction)
 {
     m_registers.clear();
-    
-    RELEASE_ASSERT(!!section == !!size);
+    RELEASE_ASSERT(!!section);
     if (!section)
         return false;
-    
+
+#if OS(DARWIN)
     RELEASE_ASSERT(size >= sizeof(CompactUnwind));
     
     CompactUnwind* data = bitwise_cast<CompactUnwind*>(section);
@@ -157,7 +690,56 @@ bool UnwindInfo::parse(void* section, size_t size, GeneratedFunction generatedFu
 #else
 #error "Unrecognized architecture"
 #endif
-    
+
+#elif OS(LINUX)
+    FDE_Info fdeInfo;
+    CIE_Info cieInfo;
+    PrologInfo prolog;
+
+    findFDE((uintptr_t)generatedFunction, (uintptr_t)section, size, &fdeInfo, &cieInfo);
+    parseFDEInstructions(fdeInfo, cieInfo, &prolog);
+
+#if CPU(X86_64)
+    RELEASE_ASSERT(prolog.cfaRegister == UNW_X86_64_rbp);
+    RELEASE_ASSERT(prolog.cfaRegisterOffset == 16);
+    RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].saved);
+    RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].offset == -prolog.cfaRegisterOffset);
+
+    for (int i = 0; i < MaxRegisterNumber; ++i) {
+        if (prolog.savedRegisters[i].saved) {
+            switch (i) {
+            case UNW_X86_64_rbx:
+                m_registers.append(RegisterAtOffset(X86Registers::ebx, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case UNW_X86_64_r12:
+                m_registers.append(RegisterAtOffset(X86Registers::r12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case UNW_X86_64_r13:
+                m_registers.append(RegisterAtOffset(X86Registers::r13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case UNW_X86_64_r14:
+                m_registers.append(RegisterAtOffset(X86Registers::r14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case UNW_X86_64_r15:
+                m_registers.append(RegisterAtOffset(X86Registers::r15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case UNW_X86_64_rbp:
+                m_registers.append(RegisterAtOffset(X86Registers::ebp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
+                break;
+            case DW_X86_64_RET_addr:
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
+            }
+        }
+    }
+#elif CPU(ARM64)
+    // FIXME: Implement stackunwinding based on eh_frame on ARM64
+#else
+#error "Unrecognized architecture"
+#endif
+
+#endif
     std::sort(m_registers.begin(), m_registers.end());
     return true;
 }
index a4e7abd..6d2bf63 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014 Samsung Electronics
+ * Copyright (C) 2014 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
diff --git a/Source/cmake/FindLIBCXXABI.cmake b/Source/cmake/FindLIBCXXABI.cmake
deleted file mode 100644 (file)
index 9ac7415..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# - Try to find libcxxabi
-# This module defines the following variable:
-#
-#  LIBCXXABI_FOUND - true if libcxxabi found
-#  LIBCXXABI_INCLUDE_DIRS - the libcxxabi include directories
-#
-# Copyright (C) 2014 Samsung Electronics
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1.  Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer.
-# 2.  Redistributions in binary form must reproduce the above copyright
-#     notice, this list of conditions and the following disclaimer in the
-#     documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
-# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-find_path(LIBCXXABI_INCLUDE_DIRS
-    NAMES mach-o/compact_unwind_encoding.h
-    PATH_SUFFIXES libcxxabi
-)
-
-include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Libcxxabi DEFAULT_MSG LIBCXXABI_INCLUDE_DIRS)
-
-mark_as_advanced(
-    LIBCXXABI_INCLUDE_DIRS
-)
index fd0acfa..e692a44 100644 (file)
@@ -305,7 +305,6 @@ endif ()
 
 if (ENABLE_FTL_JIT)
     find_package(LLVM REQUIRED)
-    find_package(LIBCXXABI REQUIRED)
     set(HAVE_LLVM ON)
 endif ()
 
index baf4f3d..23234aa 100644 (file)
@@ -1,3 +1,15 @@
+2014-09-11  László Langó  <llango.u-szeged@partner.samsung.com>
+
+        [JavaScriptCore] Fix FTL on platform EFL.
+        https://bugs.webkit.org/show_bug.cgi?id=133571
+
+        Reviewed by Filip Pizlo.
+
+        * efl/install-dependencies: Revert r169181.
+        * efl/jhbuild.modules: Clone and build a custom branch.
+        This branch contains some fix for FTL of platform EFL.
+        The branch is a fork of llvm r206311.
+
 2014-09-10  Tanay C  <tanay.c@samsung.com>
 
         [EFL][WK2] Minibrowser : Shift+Scroll navigate to back or forward url's
index 845d3c5..b11306e 100755 (executable)
@@ -36,7 +36,6 @@ function installDependenciesWithApt {
         gperf \
         gtk-doc-tools \
         libatk1.0-dev \
-        libc++abi-dev \
         libdbus-1-dev \
         libenchant-dev \
         libespeak-dev \
index 1434a1e..632a666 100644 (file)
@@ -48,8 +48,8 @@
       href="http://gstreamer.freedesktop.org/src/"/>
   <repository type="tarball" name="downloads.sourceforge.net"
       href="http://downloads.sourceforge.net/project/"/>
-  <repository type="svn" name="llvm.org"
-      href="http://llvm.org/svn/llvm-project/llvm/"/> 
+  <repository type="git" name="llvm.org"
+      href="https://github.com/pille5"/>
 
   <autotools id="cairo" autogen-sh="configure"
              makeargs="CFLAGS='-fno-lto' CXXFLAGS='-fno-lto' LDFLAGS='-fno-lto'">
   <autotools id="llvm"
              autogen-sh="configure"
              autogenargs="--enable-optimized=yes --enable-backtraces=no --enable-targets=x86_64 --enable-zlib=no --enable-terminfo=no --enable-crash-overrides=no --disable-expensive-checks --disable-debug-runtime --disable-assertions">
-    <branch repo="llvm.org" module="trunk" checkoutdir="llvm" version="r206311" revision="206311"/>
+    <branch repo="llvm.org" module="llvm.git" revision="FTL_fixes_for_EFL" checkoutdir="llvm" version="r206311"/>
   </autotools>
 
   <autotools id="fontconfig"