qt5_qml.patch From: Christian Prochaska --- qtdeclarative/src/qml/qml/qqmlimport.cpp | 9 qtdeclarative/src/qml/qml/v8/qv8qobjectwrapper.cpp | 4 qtdeclarative/src/qml/types/qqmldelegatemodel_p.h | 2 qtjsbackend/src/3rdparty/v8/src/platform-genode.cc | 701 ++++++++++++++++++++ qtjsbackend/src/v8/v8.pri | 2 5 files changed, 716 insertions(+), 2 deletions(-) create mode 100644 qtjsbackend/src/3rdparty/v8/src/platform-genode.cc diff --git a/qtdeclarative/src/qml/qml/qqmlimport.cpp b/qtdeclarative/src/qml/qml/qqmlimport.cpp index 2fbb614..5816e9a 100644 --- a/qtdeclarative/src/qml/qml/qqmlimport.cpp +++ b/qtdeclarative/src/qml/qml/qqmlimport.cpp @@ -1463,6 +1463,14 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName) { +#if defined(Q_OS_GENODE) + + return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, + QStringList() << QLatin1String(".lib.so"), + QLatin1String("qt5_")); + +#else + #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) return resolvePlugin(typeLoader, qmldirPath, qmldirPluginPath, baseName, QStringList() @@ -1512,6 +1520,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader, # endif #endif +#endif } /*! diff --git a/qtdeclarative/src/qml/qml/v8/qv8qobjectwrapper.cpp b/qtdeclarative/src/qml/qml/v8/qv8qobjectwrapper.cpp index 53f70ad..0b31aa6 100644 --- a/qtdeclarative/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ b/qtdeclarative/src/qml/qml/v8/qv8qobjectwrapper.cpp @@ -973,6 +973,8 @@ v8::Local QQmlPropertyCache::newQObject(QObject *object, QV8Engine * if (checkForDuplicates) uniqueHash.reserve(stringCache.count()); +/* disabling this code seems to avoid crashes on 32-bit Linux and NOVA */ +#if 0 // XXX TODO: Enables fast property accessors. These more than double the property access // performance, but the cost of setting up this structure hasn't been measured so // its not guaranteed that this is a win overall. We need to try and measure the cost. @@ -1032,7 +1034,7 @@ v8::Local QQmlPropertyCache::newQObject(QObject *object, QV8Engine * v8::External::New(property)); } } - +#endif if (ft.IsEmpty()) { constructor = qPersistentNew(engine->qobjectWrapper()->m_constructor); } else { diff --git a/qtdeclarative/src/qml/types/qqmldelegatemodel_p.h b/qtdeclarative/src/qml/types/qqmldelegatemodel_p.h index 5702c59..3d616b5 100644 --- a/qtdeclarative/src/qml/types/qqmldelegatemodel_p.h +++ b/qtdeclarative/src/qml/types/qqmldelegatemodel_p.h @@ -52,6 +52,8 @@ #include #include +#include + Q_DECLARE_METATYPE(QModelIndex) QT_BEGIN_NAMESPACE diff --git a/qtjsbackend/src/3rdparty/v8/src/platform-genode.cc b/qtjsbackend/src/3rdparty/v8/src/platform-genode.cc new file mode 100644 index 0000000..3a8cf90 --- /dev/null +++ b/qtjsbackend/src/3rdparty/v8/src/platform-genode.cc @@ -0,0 +1,701 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 +// OWNER OR 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. + +// Platform specific code for Genode goes here + +// Minimal include to get access to abort, fprintf and friends for bootstrapping +// messages. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "v8.h" + +#include "platform-posix.h" +#include "platform.h" +#include "vm-state-inl.h" + + +namespace v8 { +namespace internal { + +static const bool verbose = false; + +static const pthread_t kNoThread = (pthread_t) 0; + +#undef UNIMPLEMENTED +#define UNIMPLEMENTED(...) PDBG("UNIMPLEMENTED") + + +double ceiling(double x) { + return ceil(x); +} + + +// Initialize OS class early in the V8 startup. +void OS::SetUp() { + // Seed the random number generator. + UNIMPLEMENTED(); +} + + +void OS::PostSetUp() { + POSIXPostSetUp(); +} + + +void OS::TearDown() { + UNIMPLEMENTED(); +} + +int OS::ActivationFrameAlignment() { +#ifdef V8_TARGET_ARCH_ARM + // On EABI ARM targets this is required for fp correctness in the + // runtime system. + return 8; +#elif V8_TARGET_ARCH_MIPS + return 8; +#endif + // With gcc 4.4 the tree vectorization optimizer can generate code + // that requires 16 byte alignment such as movdqa on x86. + return 16; +} + + +void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { +#if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \ + (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__)) + // Only use on ARM or MIPS hardware. + MemoryBarrier(); +#else + __asm__ __volatile__("" : : : "memory"); + // An x86 store acts as a release barrier. +#endif + *ptr = value; +} + + +// Returns a string identifying the current timezone taking into +// account daylight saving. +const char* OS::LocalTimezone(double time) { + UNIMPLEMENTED(); + return ""; +} + + +// Returns the local time offset in milliseconds east of UTC without +// taking daylight savings time into account. +double OS::LocalTimeOffset() { + UNIMPLEMENTED(); + return 0; +} + + +uint64_t OS::CpuFeaturesImpliedByPlatform() { + return 0; +} + +#if 0 +CpuImplementer OS::GetCpuImplementer() { + UNIMPLEMENTED(); +} + + +bool OS::ArmCpuHasFeature(CpuFeature feature) { + UNIMPLEMENTED(); +} + + +bool OS::ArmUsingHardFloat() { + UNIMPLEMENTED(); +} +#endif + +bool OS::IsOutsideAllocatedSpace(void* address) { + UNIMPLEMENTED(); + return false; +} + +#if 0 +size_t OS::AllocateAlignment() { + UNIMPLEMENTED(); + return 0; +} +#endif + +void* OS::Allocate(const size_t requested, + size_t* allocated, + bool executable) { + //UNIMPLEMENTED(); + *allocated = requested; + return malloc(requested); +} + +#if 0 +void OS::Free(void* buf, const size_t length) { + // TODO(1240712): potential system call return value which is ignored here. + UNIMPLEMENTED(); +} + + +void OS::Guard(void* address, const size_t size) { + UNIMPLEMENTED(); +} +#endif + +void OS::Sleep(int milliseconds) { + UNIMPLEMENTED(); +} + + +void OS::Abort() { + // Minimalistic implementation for bootstrapping. + abort(); +} + +#if 0 +void OS::DebugBreak() { + UNIMPLEMENTED(); +} +#endif + +OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { + UNIMPLEMENTED(); + return NULL; +} + +#if 0 +OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, + void* initial) { + UNIMPLEMENTED(); + return NULL; +} +#endif + +void OS::LogSharedLibraryAddresses() { + UNIMPLEMENTED(); +} + + +void OS::SignalCodeMovingGC() { + UNIMPLEMENTED(); +} + +#if 0 +int OS::StackWalk(Vector frames) { + UNIMPLEMENTED(); + return 0; +} +#endif + +/* --- */ + +class Attached_rm_connection : public Genode::Rm_connection, + public Genode::Avl_node +{ + + private: + + Genode::Dataspace_capability _ds_cap; + + size_t _size; + Genode::addr_t _base_addr; + + public: + + Attached_rm_connection(size_t size, size_t alignment = 0) + : Genode::Rm_connection(0, size), + _ds_cap(dataspace()), + _size(size) + { + if (alignment == 0) { + _base_addr = Genode::env()->rm_session()->attach(_ds_cap); + } else { + for (_base_addr = alignment; + _base_addr != 0; /* wrap-around */ + _base_addr += alignment) { + try { + Genode::env()->rm_session()->attach_at(_ds_cap, _base_addr); + return; + } catch (Genode::Rm_connection::Region_conflict) { + if (verbose) + PDBG("could not attach at address 0x%lx", _base_addr); + } + } + throw Rm_connection::Region_conflict(); + } + } + + ~Attached_rm_connection() + { + Genode::env()->rm_session()->detach(_base_addr); + } + + size_t size() const { return _size; } + + void *base_addr() const { return (void*)_base_addr; } + + void attach(Genode::Dataspace_capability ds_cap, Genode::addr_t addr, + bool executable) + { + Genode::Rm_connection::attach(ds_cap, 0, 0, true, + (void*)(addr - _base_addr), + executable); + } + + Attached_rm_connection *find_by_addr(Genode::addr_t addr) + { + if (verbose) + PDBG("addr = 0x%lx, _base_addr = 0x%lx, _end_addr = 0x%lx", + addr, _base_addr, _base_addr + _size); + if ((addr >= _base_addr) && (addr < _base_addr + _size)) + return this; + + Attached_rm_connection *next = child(addr > _base_addr); + return next ? next->find_by_addr(addr) : 0; + } + + /** + * Avl_node interface + */ + bool higher(Attached_rm_connection *other) + { + return ((Genode::addr_t)other->base_addr() > _base_addr); + } +}; + + +static Genode::Avl_tree &vm_registry() +{ + static Genode::Avl_tree _vm_registry; + return _vm_registry; +} + + +static void *reserve_region(size_t size, size_t alignment = 0) +{ + Attached_rm_connection *rm; + try { + rm = new Attached_rm_connection(size, alignment); + } catch (Attached_rm_connection::Region_conflict) { + PDBG("could not reserve region"); + return 0; + } + vm_registry().insert(rm); + if (verbose) + PDBG("base_addr = 0x%p", rm->base_addr()); + return rm->base_addr(); +} + +/* --- */ + +VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } + + +VirtualMemory::VirtualMemory(size_t size) { + if (verbose) + PDBG("size = 0x%zx", size); + address_ = ReserveRegion(size); + size_ = size; +} + + +VirtualMemory::VirtualMemory(size_t size, size_t alignment) { + if (verbose) + PDBG("size = 0x%zx, alignment = 0x%zx", size, alignment); + address_ = reserve_region(size, alignment); + size_ = size; +} + + +VirtualMemory::~VirtualMemory() { + if (IsReserved()) { + bool result = ReleaseRegion(address(), size()); + ASSERT(result); + USE(result); + } +} + + +bool VirtualMemory::IsReserved() { + return address_ != NULL; +} + + +void VirtualMemory::Reset() { + address_ = NULL; + size_ = 0; +} + + +bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { + return CommitRegion(address, size, is_executable); +} + + + +bool VirtualMemory::Uncommit(void* address, size_t size) { + return UncommitRegion(address, size); +} + + +bool VirtualMemory::Guard(void* address) { + UNIMPLEMENTED(); + return true; +} + + +void* VirtualMemory::ReserveRegion(size_t size) { + return reserve_region(size); +} + + +bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { + if (verbose) + PDBG("base = 0x%p, size = 0x%zx", base, size); + Attached_rm_connection *rm = vm_registry().first(); + rm = rm->find_by_addr((Genode::addr_t)base); + if (!rm) { + if (verbose) + PDBG("could not find RM connection"); + return false; + } + + Genode::Ram_dataspace_capability ds_cap = + Genode::env()->ram_session()->alloc(size); + + try { + rm->attach(ds_cap, (Genode::addr_t)base, is_executable); + } catch (Genode::Rm_session::Region_conflict) { + return false; + } + + return true; +} + + +bool VirtualMemory::UncommitRegion(void* base, size_t size) { + UNIMPLEMENTED(); + if (verbose) + PDBG("base = 0x%p, size = 0x%zx", base, size); + return false; +} + + +bool VirtualMemory::ReleaseRegion(void* base, size_t size) { + + UNIMPLEMENTED(); + +#if 0 + /* + * FIXME + * + * Unmapping of managed dataspaces is not supported on all platforms. + * To make it still work, all dataspaces attached to the sub RM session must + * be detached before detaching the sub RM session. + */ + + if (verbose) + PDBG("base = 0x%p, size = 0x%zx", base, size); + Attached_rm_connection *rm = vm_registry().first(); + /* XXX: also pass the size for checking? */ + rm = rm->find_by_addr((Genode::addr_t)base); + if (!rm) + return false; + + vm_registry().remove(rm); + + delete rm; +#endif + + return true; +} + + +bool VirtualMemory::HasLazyCommits() { + // TODO(alph): implement for the platform. + return false; +} + + +class Thread::PlatformData : public Malloced { + public: + PlatformData() : thread_(kNoThread) {} + + pthread_t thread_; // Thread handle for pthread. +}; + + +Thread::Thread(const Options& options) + : data_(new PlatformData()), + stack_size_(options.stack_size()) { + set_name(options.name()); +} + + +Thread::~Thread() { + delete data_; +} + + +static void* ThreadEntry(void* arg) { + Thread* thread = reinterpret_cast(arg); + // This is also initialized by the first argument to pthread_create() but we + // don't know which thread will run first (the original thread or the new + // one) so we initialize it here too. +#ifdef PR_SET_NAME + prctl(PR_SET_NAME, + reinterpret_cast(thread->name()), // NOLINT + 0, 0, 0); +#endif + thread->data()->thread_ = pthread_self(); + ASSERT(thread->data()->thread_ != kNoThread); + thread->Run(); + return NULL; +} + + +void Thread::set_name(const char* name) { + strncpy(name_, name, sizeof(name_)); + name_[sizeof(name_) - 1] = '\0'; +} + + +void Thread::Start() { + pthread_attr_t* attr_ptr = NULL; + pthread_attr_t attr; + if (stack_size_ > 0) { + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, static_cast(stack_size_)); + attr_ptr = &attr; + } + int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); + CHECK_EQ(0, result); + ASSERT(data_->thread_ != kNoThread); +} + + +void Thread::Join() { + pthread_join(data_->thread_, NULL); +} + + +Thread::LocalStorageKey Thread::CreateThreadLocalKey() { + pthread_key_t key; + int result = pthread_key_create(&key, NULL); + USE(result); + ASSERT(result == 0); + return static_cast(key); +} + + +void Thread::DeleteThreadLocalKey(LocalStorageKey key) { + pthread_key_t pthread_key = static_cast(key); + int result = pthread_key_delete(pthread_key); + USE(result); + ASSERT(result == 0); +} + + +void* Thread::GetThreadLocal(LocalStorageKey key) { + pthread_key_t pthread_key = static_cast(key); + return pthread_getspecific(pthread_key); +} + + +void Thread::SetThreadLocal(LocalStorageKey key, void* value) { + pthread_key_t pthread_key = static_cast(key); + pthread_setspecific(pthread_key, value); +} + + +void Thread::YieldCPU() { + UNIMPLEMENTED(); +} + + +class GenodeMutex : public Mutex { + public: + GenodeMutex() { + pthread_mutexattr_t attrs; + int result = pthread_mutexattr_init(&attrs); + ASSERT(result == 0); + result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); + ASSERT(result == 0); + result = pthread_mutex_init(&mutex_, &attrs); + ASSERT(result == 0); + USE(result); + } + + virtual ~GenodeMutex() { pthread_mutex_destroy(&mutex_); } + + virtual int Lock() { + int result = pthread_mutex_lock(&mutex_); + return result; + } + + virtual int Unlock() { + int result = pthread_mutex_unlock(&mutex_); + return result; + } + + virtual bool TryLock() { + int result = pthread_mutex_trylock(&mutex_); + // Return false if the lock is busy and locking failed. + if (result == EBUSY) { + return false; + } + ASSERT(result == 0); // Verify no other errors. + return true; + } + + private: + pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. +}; + + +Mutex* OS::CreateMutex() { + return new GenodeMutex(); +} + + +class GenodeSemaphore : public Semaphore { + public: + explicit GenodeSemaphore(int count) { sem_init(&sem_, 0, count); } + virtual ~GenodeSemaphore() { sem_destroy(&sem_); } + + virtual void Wait(); + virtual bool Wait(int timeout); + virtual void Signal() { sem_post(&sem_); } + private: + sem_t sem_; +}; + + +void GenodeSemaphore::Wait() { + while (true) { + int result = sem_wait(&sem_); + if (result == 0) return; // Successfully got semaphore. + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. + } +} + + +#ifndef TIMEVAL_TO_TIMESPEC +#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} while (false) +#endif + + +bool GenodeSemaphore::Wait(int timeout) { + const long kOneSecondMicros = 1000000; // NOLINT + + // Split timeout into second and nanosecond parts. + struct timeval delta; + delta.tv_usec = timeout % kOneSecondMicros; + delta.tv_sec = timeout / kOneSecondMicros; + + struct timeval current_time; + // Get the current time. + if (gettimeofday(¤t_time, NULL) == -1) { + return false; + } + + // Calculate time for end of timeout. + struct timeval end_time; + timeradd(¤t_time, &delta, &end_time); + + struct timespec ts; + TIMEVAL_TO_TIMESPEC(&end_time, &ts); + // Wait for semaphore signalled or timeout. + while (true) { + int result = sem_timedwait(&sem_, &ts); + if (result == 0) return true; // Successfully got semaphore. + if (result > 0) { + // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1. + errno = result; + result = -1; + } + if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. + } +} + + +Semaphore* OS::CreateSemaphore(int count) { + return new GenodeSemaphore(count); +} + + +class Sampler::PlatformData : public Malloced { + public: + PlatformData() { + UNIMPLEMENTED(); + } +}; + + +Sampler::Sampler(Isolate *isolate, int interval) + : isolate_(isolate), + interval_(interval), + profiling_(false), + active_(false), + samples_taken_(0) { + UNIMPLEMENTED(); + // Shared setup follows. + data_ = new PlatformData; +} + + +Sampler::~Sampler() { + UNIMPLEMENTED(); + // Shared tear down follows. + delete data_; +} + + +void Sampler::Start() { + UNIMPLEMENTED(); +} + + +void Sampler::Stop() { + UNIMPLEMENTED(); +} + + +} } // namespace v8::internal diff --git a/qtjsbackend/src/v8/v8.pri b/qtjsbackend/src/v8/v8.pri index 3a563ff..6a83034 100644 --- a/qtjsbackend/src/v8/v8.pri +++ b/qtjsbackend/src/v8/v8.pri @@ -265,7 +265,7 @@ SOURCES += \ LIBS += -lexecinfo } else:unix:!qnx { SOURCES += \ - $$V8SRC/platform-linux.cc \ + $$V8SRC/platform-genode.cc \ $$V8SRC/platform-posix.cc }