2013-08-14 08:17:31 +00:00
/****************************************************************************
* *
2016-01-19 09:38:36 +00:00
* * Copyright ( C ) 2016 The Qt Company Ltd .
* * Contact : https : //www.qt.io/licensing/
2013-08-14 08:17:31 +00:00
* *
* * This file is part of the QtQml module of the Qt Toolkit .
* *
2016-01-19 09:38:36 +00:00
* * $ QT_BEGIN_LICENSE : LGPL $
2013-08-14 08:17:31 +00:00
* * Commercial License Usage
* * Licensees holding valid commercial Qt licenses may use this file in
* * accordance with the commercial license agreement provided with the
* * Software or , alternatively , in accordance with the terms contained in
2015-01-28 11:55:39 +00:00
* * a written agreement between you and The Qt Company . For licensing terms
2016-01-19 09:38:36 +00:00
* * and conditions see https : //www.qt.io/terms-conditions. For further
* * information use the contact form at https : //www.qt.io/contact-us.
2013-08-14 08:17:31 +00:00
* *
* * GNU Lesser General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU Lesser
2016-01-19 09:38:36 +00:00
* * General Public License version 3 as published by the Free Software
* * Foundation and appearing in the file LICENSE . LGPL3 included in the
* * packaging of this file . Please review the following information to
* * ensure the GNU Lesser General Public License version 3 requirements
* * will be met : https : //www.gnu.org/licenses/lgpl-3.0.html.
2013-08-14 08:17:31 +00:00
* *
2016-01-19 09:38:36 +00:00
* * GNU General Public License Usage
* * Alternatively , this file may be used under the terms of the GNU
* * General Public License version 2.0 or ( at your option ) the GNU General
* * Public license version 3 or any later version approved by the KDE Free
* * Qt Foundation . The licenses are as published by the Free Software
* * Foundation and appearing in the file LICENSE . GPL2 and LICENSE . GPL3
* * included in the packaging of this file . Please review the following
* * information to ensure the GNU General Public License requirements will
* * be met : https : //www.gnu.org/licenses/gpl-2.0.html and
* * https : //www.gnu.org/licenses/gpl-3.0.html.
2013-08-14 08:17:31 +00:00
* *
* * $ QT_END_LICENSE $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "qv4compileddata_p.h"
# include "qv4jsir_p.h"
2015-02-14 21:46:41 +00:00
# include <private/qv4value_p.h>
2014-03-12 15:55:06 +00:00
# ifndef V4_BOOTSTRAP
2013-08-14 08:17:37 +00:00
# include <private/qv4engine_p.h>
2013-08-14 13:44:53 +00:00
# include <private/qv4function_p.h>
2013-08-29 12:31:32 +00:00
# include <private/qv4objectproto_p.h>
2013-08-15 10:48:05 +00:00
# include <private/qv4lookup_p.h>
2013-08-15 13:54:36 +00:00
# include <private/qv4regexpobject_p.h>
2015-04-09 08:23:17 +00:00
# include <private/qqmlpropertycache_p.h>
2016-05-29 17:05:27 +00:00
# include <private/qqmltypeloader_p.h>
2016-05-29 17:21:54 +00:00
# include <private/qqmlengine_p.h>
# include <QQmlPropertyMap>
2016-07-21 15:12:52 +00:00
# include <QDateTime>
2016-06-06 09:46:01 +00:00
# include <QSaveFile>
2016-06-06 14:19:47 +00:00
# include <QFile>
# include <QFileInfo>
# include <QScopedValueRollback>
2014-03-12 15:55:06 +00:00
# endif
2014-03-27 16:07:06 +00:00
# include <private/qqmlirbuilder_p.h>
2014-03-06 15:19:42 +00:00
# include <QCoreApplication>
2016-08-03 13:15:51 +00:00
# include <QCryptographicHash>
2013-08-14 08:17:31 +00:00
2013-09-12 09:06:59 +00:00
# include <algorithm>
2013-08-18 13:35:02 +00:00
QT_BEGIN_NAMESPACE
2013-08-14 08:17:31 +00:00
namespace QV4 {
namespace CompiledData {
2014-03-12 15:55:06 +00:00
# ifndef V4_BOOTSTRAP
2015-04-09 08:23:17 +00:00
CompilationUnit : : CompilationUnit ( )
: data ( 0 )
, engine ( 0 )
, runtimeStrings ( 0 )
, runtimeLookups ( 0 )
, runtimeRegularExpressions ( 0 )
, runtimeClasses ( 0 )
2016-05-29 16:47:57 +00:00
, totalBindingsCount ( 0 )
, totalParserStatusCount ( 0 )
, totalObjectCount ( 0 )
2016-05-29 16:58:07 +00:00
, metaTypeId ( - 1 )
, listMetaTypeId ( - 1 )
, isRegisteredWithEngine ( false )
2015-04-09 08:23:17 +00:00
{ }
2013-08-14 08:17:37 +00:00
CompilationUnit : : ~ CompilationUnit ( )
{
2013-09-19 07:32:42 +00:00
unlink ( ) ;
2016-05-20 13:22:31 +00:00
if ( data & & ! ( data - > flags & QV4 : : CompiledData : : Unit : : StaticData ) )
2016-06-03 09:23:25 +00:00
free ( const_cast < Unit * > ( data ) ) ;
2016-05-20 13:22:31 +00:00
data = 0 ;
2013-08-14 08:17:37 +00:00
}
QV4 : : Function * CompilationUnit : : linkToEngine ( ExecutionEngine * engine )
{
2013-08-15 12:11:19 +00:00
this - > engine = engine ;
engine - > compilationUnits . insert ( this ) ;
2014-03-18 08:20:45 +00:00
Q_ASSERT ( ! runtimeStrings ) ;
Q_ASSERT ( data ) ;
2014-11-12 15:07:56 +00:00
runtimeStrings = ( QV4 : : Heap : : String * * ) malloc ( data - > stringTableSize * sizeof ( QV4 : : Heap : : String * ) ) ;
2013-09-20 13:13:14 +00:00
// memset the strings to 0 in case a GC run happens while we're within the loop below
2014-11-12 15:07:56 +00:00
memset ( runtimeStrings , 0 , data - > stringTableSize * sizeof ( QV4 : : Heap : : String * ) ) ;
for ( uint i = 0 ; i < data - > stringTableSize ; + + i )
runtimeStrings [ i ] = engine - > newIdentifier ( data - > stringAt ( i ) ) ;
2013-08-14 08:17:37 +00:00
2014-01-24 21:55:39 +00:00
runtimeRegularExpressions = new QV4 : : Value [ data - > regexpTableSize ] ;
2013-09-20 13:13:14 +00:00
// memset the regexps to 0 in case a GC run happens while we're within the loop below
2014-01-24 21:55:39 +00:00
memset ( runtimeRegularExpressions , 0 , data - > regexpTableSize * sizeof ( QV4 : : Value ) ) ;
2013-11-01 11:38:32 +00:00
for ( uint i = 0 ; i < data - > regexpTableSize ; + + i ) {
2013-08-15 13:54:36 +00:00
const CompiledData : : RegExp * re = data - > regexpAt ( i ) ;
int flags = 0 ;
if ( re - > flags & CompiledData : : RegExp : : RegExp_Global )
2014-02-14 12:58:40 +00:00
flags | = IR : : RegExp : : RegExp_Global ;
2013-08-15 13:54:36 +00:00
if ( re - > flags & CompiledData : : RegExp : : RegExp_IgnoreCase )
2014-02-14 12:58:40 +00:00
flags | = IR : : RegExp : : RegExp_IgnoreCase ;
2013-08-15 13:54:36 +00:00
if ( re - > flags & CompiledData : : RegExp : : RegExp_Multiline )
2014-02-14 12:58:40 +00:00
flags | = IR : : RegExp : : RegExp_Multiline ;
2014-11-12 15:07:56 +00:00
runtimeRegularExpressions [ i ] = engine - > newRegExpObject ( data - > stringAt ( re - > stringIndex ) , flags ) ;
2013-08-15 13:54:36 +00:00
}
2013-08-15 10:48:05 +00:00
if ( data - > lookupTableSize ) {
runtimeLookups = new QV4 : : Lookup [ data - > lookupTableSize ] ;
2013-10-11 12:58:45 +00:00
memset ( runtimeLookups , 0 , data - > lookupTableSize * sizeof ( QV4 : : Lookup ) ) ;
2013-08-15 10:48:05 +00:00
const CompiledData : : Lookup * compiledLookups = data - > lookupTable ( ) ;
for ( uint i = 0 ; i < data - > lookupTableSize ; + + i ) {
QV4 : : Lookup * l = runtimeLookups + i ;
2016-07-12 12:19:09 +00:00
Lookup : : Type type = Lookup : : Type ( uint ( compiledLookups [ i ] . type_and_flags ) ) ;
2014-01-24 12:16:55 +00:00
if ( type = = CompiledData : : Lookup : : Type_Getter )
2013-08-15 10:48:05 +00:00
l - > getter = QV4 : : Lookup : : getterGeneric ;
2014-01-24 12:16:55 +00:00
else if ( type = = CompiledData : : Lookup : : Type_Setter )
2013-08-15 10:48:05 +00:00
l - > setter = QV4 : : Lookup : : setterGeneric ;
2014-01-24 12:16:55 +00:00
else if ( type = = CompiledData : : Lookup : : Type_GlobalGetter )
2013-08-15 10:48:05 +00:00
l - > globalGetter = QV4 : : Lookup : : globalGetterGeneric ;
2014-01-24 12:16:55 +00:00
else if ( type = = CompiledData : : Lookup : : Type_IndexedGetter )
2014-01-17 11:19:34 +00:00
l - > indexedGetter = QV4 : : Lookup : : indexedGetterGeneric ;
2014-01-24 12:16:55 +00:00
else if ( type = = CompiledData : : Lookup : : Type_IndexedSetter )
l - > indexedSetter = QV4 : : Lookup : : indexedSetterGeneric ;
2013-08-15 10:48:05 +00:00
2013-11-01 11:38:32 +00:00
for ( int j = 0 ; j < QV4 : : Lookup : : Size ; + + j )
l - > classList [ j ] = 0 ;
2013-08-15 10:48:05 +00:00
l - > level = - 1 ;
l - > index = UINT_MAX ;
2014-11-12 15:07:56 +00:00
l - > nameIndex = compiledLookups [ i ] . nameIndex ;
2014-01-24 12:16:55 +00:00
if ( type = = CompiledData : : Lookup : : Type_IndexedGetter | | type = = CompiledData : : Lookup : : Type_IndexedSetter )
2014-01-17 11:19:34 +00:00
l - > engine = engine ;
2013-08-15 10:48:05 +00:00
}
}
2013-08-16 11:21:31 +00:00
if ( data - > jsClassTableSize ) {
runtimeClasses = ( QV4 : : InternalClass * * ) malloc ( data - > jsClassTableSize * sizeof ( QV4 : : InternalClass * ) ) ;
2013-11-01 11:38:32 +00:00
for ( uint i = 0 ; i < data - > jsClassTableSize ; + + i ) {
2013-08-16 11:21:31 +00:00
int memberCount = 0 ;
const CompiledData : : JSClassMember * member = data - > jsClassAt ( i , & memberCount ) ;
2015-01-10 19:35:18 +00:00
QV4 : : InternalClass * klass = engine - > emptyClass ;
2013-08-16 11:21:31 +00:00
for ( int j = 0 ; j < memberCount ; + + j , + + member )
2014-11-12 19:07:27 +00:00
klass = klass - > addMember ( runtimeStrings [ member - > nameOffset ] - > identifier , member - > isAccessor ? QV4 : : Attr_Accessor : QV4 : : Attr_Data ) ;
2013-08-16 11:21:31 +00:00
runtimeClasses [ i ] = klass ;
}
}
2016-07-14 18:39:58 +00:00
# if Q_BYTE_ORDER == Q_BIG_ENDIAN
Value * bigEndianConstants = new Value [ data - > constantTableSize ] ;
const LEUInt64 * littleEndianConstants = data - > constants ( ) ;
for ( uint i = 0 ; i < data - > constantTableSize ; + + i )
bigEndianConstants [ i ] = Value : : fromReturnedValue ( littleEndianConstants [ i ] ) ;
constants = bigEndianConstants ;
# else
constants = reinterpret_cast < const Value * > ( data - > constants ( ) ) ;
# endif
2013-08-19 06:31:35 +00:00
linkBackendToEngine ( engine ) ;
2013-08-16 16:35:29 +00:00
2013-10-18 13:36:40 +00:00
if ( data - > indexOfRootFunction ! = - 1 )
return runtimeFunctions [ data - > indexOfRootFunction ] ;
else
return 0 ;
2013-08-14 08:17:37 +00:00
}
2013-09-19 07:32:42 +00:00
void CompilationUnit : : unlink ( )
{
if ( engine )
engine - > compilationUnits . erase ( engine - > compilationUnits . find ( this ) ) ;
2016-05-29 07:33:26 +00:00
2016-05-29 16:58:07 +00:00
if ( isRegisteredWithEngine ) {
2016-06-14 13:44:09 +00:00
Q_ASSERT ( data & & quint32 ( propertyCaches . count ( ) ) > data - > indexOfRootObject & & propertyCaches . at ( data - > indexOfRootObject ) ) ;
2016-05-29 16:58:07 +00:00
QQmlEnginePrivate * qmlEngine = QQmlEnginePrivate : : get ( propertyCaches . at ( data - > indexOfRootObject ) - > engine ) ;
qmlEngine - > unregisterInternalCompositeType ( this ) ;
isRegisteredWithEngine = false ;
}
2016-05-29 07:33:26 +00:00
propertyCaches . clear ( ) ;
2016-05-29 17:05:27 +00:00
for ( int ii = 0 ; ii < dependentScripts . count ( ) ; + + ii )
dependentScripts . at ( ii ) - > release ( ) ;
dependentScripts . clear ( ) ;
2016-05-29 16:42:28 +00:00
importCache = nullptr ;
2016-05-29 17:21:54 +00:00
qDeleteAll ( resolvedTypes ) ;
resolvedTypes . clear ( ) ;
2013-09-19 07:32:42 +00:00
engine = 0 ;
free ( runtimeStrings ) ;
runtimeStrings = 0 ;
delete [ ] runtimeLookups ;
runtimeLookups = 0 ;
delete [ ] runtimeRegularExpressions ;
runtimeRegularExpressions = 0 ;
free ( runtimeClasses ) ;
runtimeClasses = 0 ;
qDeleteAll ( runtimeFunctions ) ;
runtimeFunctions . clear ( ) ;
2016-07-14 18:39:58 +00:00
# if Q_BYTE_ORDER == Q_BIG_ENDIAN
delete [ ] constants ;
# endif
2013-09-19 07:32:42 +00:00
}
2013-11-02 15:30:26 +00:00
void CompilationUnit : : markObjects ( QV4 : : ExecutionEngine * e )
2013-08-15 12:11:19 +00:00
{
2013-11-01 11:38:32 +00:00
for ( uint i = 0 ; i < data - > stringTableSize ; + + i )
2014-07-23 11:56:43 +00:00
if ( runtimeStrings [ i ] )
runtimeStrings [ i ] - > mark ( e ) ;
2013-10-11 12:58:45 +00:00
if ( runtimeRegularExpressions ) {
2013-11-01 11:38:32 +00:00
for ( uint i = 0 ; i < data - > regexpTableSize ; + + i )
2013-11-02 15:30:26 +00:00
runtimeRegularExpressions [ i ] . mark ( e ) ;
2013-10-11 12:58:45 +00:00
}
2013-08-15 12:11:19 +00:00
}
2016-06-01 08:55:45 +00:00
void CompilationUnit : : destroy ( )
{
QQmlEngine * qmlEngine = 0 ;
2016-07-13 10:03:20 +00:00
if ( engine & & engine - > v8Engine )
qmlEngine = engine - > v8Engine - > engine ( ) ;
2016-06-01 08:55:45 +00:00
if ( qmlEngine )
QQmlEnginePrivate : : deleteInEngineThread ( qmlEngine , this ) ;
else
delete this ;
}
2016-05-25 12:55:44 +00:00
IdentifierHash < int > CompilationUnit : : namedObjectsPerComponent ( int componentObjectIndex )
{
auto it = namedObjectsPerComponentCache . find ( componentObjectIndex ) ;
if ( it = = namedObjectsPerComponentCache . end ( ) ) {
IdentifierHash < int > namedObjectCache ( engine ) ;
const CompiledData : : Object * component = data - > objectAt ( componentObjectIndex ) ;
2016-07-12 12:19:09 +00:00
const LEUInt32 * namedObjectIndexPtr = component - > namedObjectsInComponentTable ( ) ;
2016-05-25 12:55:44 +00:00
for ( quint32 i = 0 ; i < component - > nNamedObjectsInComponent ; + + i , + + namedObjectIndexPtr ) {
const CompiledData : : Object * namedObject = data - > objectAt ( * namedObjectIndexPtr ) ;
namedObjectCache . add ( runtimeStrings [ namedObject - > idNameIndex ] , namedObject - > id ) ;
}
it = namedObjectsPerComponentCache . insert ( componentObjectIndex , namedObjectCache ) ;
}
return * it ;
}
2016-06-20 06:32:21 +00:00
void CompilationUnit : : finalize ( QQmlEnginePrivate * engine )
2016-06-16 11:29:36 +00:00
{
2016-06-20 06:32:21 +00:00
// Add to type registry of composites
if ( propertyCaches . needsVMEMetaObject ( data - > indexOfRootObject ) )
engine - > registerInternalCompositeType ( this ) ;
else {
const QV4 : : CompiledData : : Object * obj = objectAt ( data - > indexOfRootObject ) ;
auto * typeRef = resolvedTypes . value ( obj - > inheritedTypeNameIndex ) ;
Q_ASSERT ( typeRef ) ;
if ( typeRef - > compilationUnit ) {
metaTypeId = typeRef - > compilationUnit - > metaTypeId ;
listMetaTypeId = typeRef - > compilationUnit - > listMetaTypeId ;
} else {
metaTypeId = typeRef - > type - > typeId ( ) ;
listMetaTypeId = typeRef - > type - > qListTypeId ( ) ;
}
}
2016-06-16 11:29:36 +00:00
// Collect some data for instantiation later.
int bindingCount = 0 ;
int parserStatusCount = 0 ;
int objectCount = 0 ;
for ( quint32 i = 0 ; i < data - > nObjects ; + + i ) {
const QV4 : : CompiledData : : Object * obj = data - > objectAt ( i ) ;
bindingCount + = obj - > nBindings ;
if ( auto * typeRef = resolvedTypes . value ( obj - > inheritedTypeNameIndex ) ) {
if ( QQmlType * qmlType = typeRef - > type ) {
if ( qmlType - > parserStatusCast ( ) ! = - 1 )
+ + parserStatusCount ;
}
+ + objectCount ;
if ( typeRef - > compilationUnit ) {
bindingCount + = typeRef - > compilationUnit - > totalBindingsCount ;
parserStatusCount + = typeRef - > compilationUnit - > totalParserStatusCount ;
objectCount + = typeRef - > compilationUnit - > totalObjectCount ;
}
}
}
totalBindingsCount = bindingCount ;
totalParserStatusCount = parserStatusCount ;
totalObjectCount = objectCount ;
}
2016-06-06 09:46:01 +00:00
2016-07-28 15:40:36 +00:00
bool CompilationUnit : : verifyChecksum ( QQmlEngine * engine ,
const ResolvedTypeReferenceMap & dependentTypes ) const
{
if ( dependentTypes . isEmpty ( ) ) {
for ( size_t i = 0 ; i < sizeof ( data - > dependencyMD5Checksum ) ; + + i ) {
if ( data - > dependencyMD5Checksum [ i ] ! = 0 )
return false ;
}
return true ;
}
QCryptographicHash hash ( QCryptographicHash : : Md5 ) ;
if ( ! dependentTypes . addToHash ( & hash , engine ) )
return false ;
QByteArray checksum = hash . result ( ) ;
Q_ASSERT ( checksum . size ( ) = = sizeof ( data - > dependencyMD5Checksum ) ) ;
return memcmp ( data - > dependencyMD5Checksum , checksum . constData ( ) ,
sizeof ( data - > dependencyMD5Checksum ) ) = = 0 ;
}
2016-08-01 13:57:53 +00:00
bool CompilationUnit : : saveToDisk ( const QUrl & unitUrl , QString * errorString )
2016-06-06 09:46:01 +00:00
{
errorString - > clear ( ) ;
2016-07-29 14:20:19 +00:00
if ( data - > sourceTimeStamp = = 0 ) {
* errorString = QStringLiteral ( " Missing time stamp for source file " ) ;
return false ;
}
2016-06-06 09:46:01 +00:00
if ( ! unitUrl . isLocalFile ( ) ) {
* errorString = QStringLiteral ( " File has to be a local file. " ) ;
return false ;
}
// Foo.qml -> Foo.qmlc
QSaveFile cacheFile ( unitUrl . toLocalFile ( ) + QLatin1Char ( ' c ' ) ) ;
if ( ! cacheFile . open ( QIODevice : : WriteOnly | QIODevice : : Truncate ) ) {
* errorString = cacheFile . errorString ( ) ;
return false ;
}
QByteArray modifiedUnit ;
modifiedUnit . resize ( data - > unitSize ) ;
memcpy ( modifiedUnit . data ( ) , data , data - > unitSize ) ;
const char * dataPtr = modifiedUnit . data ( ) ;
Unit * unitPtr ;
memcpy ( & unitPtr , & dataPtr , sizeof ( unitPtr ) ) ;
unitPtr - > flags | = Unit : : StaticData ;
prepareCodeOffsetsForDiskStorage ( unitPtr ) ;
qint64 headerWritten = cacheFile . write ( modifiedUnit ) ;
if ( headerWritten ! = modifiedUnit . size ( ) ) {
* errorString = cacheFile . errorString ( ) ;
return false ;
}
if ( ! saveCodeToDisk ( & cacheFile , unitPtr , errorString ) )
return false ;
if ( ! cacheFile . commit ( ) ) {
* errorString = cacheFile . errorString ( ) ;
return false ;
}
return true ;
}
2016-07-21 14:30:57 +00:00
bool CompilationUnit : : loadFromDisk ( const QUrl & url , EvalISelFactory * iselFactory , QString * errorString )
2016-06-06 14:19:47 +00:00
{
if ( ! url . isLocalFile ( ) ) {
* errorString = QStringLiteral ( " File has to be a local file. " ) ;
return false ;
}
2016-07-21 14:30:57 +00:00
const QString sourcePath = url . toLocalFile ( ) ;
QScopedPointer < QFile > cacheFile ( new QFile ( sourcePath + QLatin1Char ( ' c ' ) ) ) ;
2016-06-06 14:19:47 +00:00
if ( ! cacheFile - > open ( QIODevice : : ReadOnly ) ) {
* errorString = cacheFile - > errorString ( ) ;
return false ;
}
2016-07-21 14:30:57 +00:00
{
CompiledData : : Unit header ;
qint64 bytesRead = cacheFile - > read ( reinterpret_cast < char * > ( & header ) , sizeof ( header ) ) ;
if ( bytesRead ! = sizeof ( header ) ) {
* errorString = QStringLiteral ( " File too small for the header fields " ) ;
return false ;
}
if ( strncmp ( header . magic , CompiledData : : magic_str , sizeof ( header . magic ) ) ) {
* errorString = QStringLiteral ( " Magic bytes in the header do not match " ) ;
return false ;
}
if ( header . version ! = quint32 ( QV4_DATA_STRUCTURE_VERSION ) ) {
* errorString = QString : : fromUtf8 ( " V4 data structure version mismatch. Found %1 expected %2 " ) . arg ( header . version , 0 , 16 ) . arg ( QV4_DATA_STRUCTURE_VERSION , 0 , 16 ) ;
return false ;
}
if ( header . qtVersion ! = quint32 ( QT_VERSION ) ) {
* errorString = QString : : fromUtf8 ( " Qt version mismatch. Found %1 expected %2 " ) . arg ( header . qtVersion , 0 , 16 ) . arg ( QT_VERSION , 0 , 16 ) ;
return false ;
}
{
QFileInfo sourceCode ( sourcePath ) ;
if ( sourceCode . exists ( ) & & sourceCode . lastModified ( ) . toMSecsSinceEpoch ( ) ! = header . sourceTimeStamp ) {
* errorString = QStringLiteral ( " QML source file has a different time stamp than cached file. " ) ;
return false ;
}
}
}
// Data structure and qt version matched, so now we can access the rest of the file safely.
2016-06-06 14:19:47 +00:00
uchar * cacheData = cacheFile - > map ( /*offset*/ 0 , cacheFile - > size ( ) ) ;
if ( ! cacheData ) {
* errorString = cacheFile - > errorString ( ) ;
return false ;
}
2016-07-07 13:38:01 +00:00
const Unit * const oldDataPtr = ( data & & ! ( data - > flags & QV4 : : CompiledData : : Unit : : StaticData ) ) ? data : nullptr ;
2016-06-06 14:19:47 +00:00
QScopedValueRollback < const Unit * > dataPtrChange ( data , reinterpret_cast < const Unit * > ( cacheData ) ) ;
2016-07-19 08:13:26 +00:00
{
2016-07-21 14:30:57 +00:00
const QString foundArchitecture = stringAt ( data - > architectureIndex ) ;
const QString expectedArchitecture = QSysInfo : : buildAbi ( ) ;
if ( foundArchitecture ! = expectedArchitecture ) {
* errorString = QString : : fromUtf8 ( " Architecture mismatch. Found %1 expected %2 " ) . arg ( foundArchitecture ) . arg ( expectedArchitecture ) ;
2016-07-19 08:13:26 +00:00
return false ;
}
}
2016-07-21 14:30:57 +00:00
{
const QString foundCodeGenerator = stringAt ( data - > codeGeneratorIndex ) ;
const QString expectedCodeGenerator = iselFactory - > codeGeneratorName ;
if ( foundCodeGenerator ! = expectedCodeGenerator ) {
* errorString = QString : : fromUtf8 ( " Code generator mismatch. Found code generated by %1 but expected %2 " ) . arg ( foundCodeGenerator ) . arg ( expectedCodeGenerator ) ;
return false ;
}
}
2016-07-19 08:13:26 +00:00
2016-06-06 14:19:47 +00:00
if ( ! memoryMapCode ( errorString ) )
return false ;
dataPtrChange . commit ( ) ;
2016-07-07 13:38:01 +00:00
free ( const_cast < Unit * > ( oldDataPtr ) ) ;
2016-06-06 14:19:47 +00:00
backingFile . reset ( cacheFile . take ( ) ) ;
return true ;
}
2016-06-06 09:46:01 +00:00
void CompilationUnit : : prepareCodeOffsetsForDiskStorage ( Unit * unit )
{
Q_UNUSED ( unit ) ;
}
bool CompilationUnit : : saveCodeToDisk ( QIODevice * device , const Unit * unit , QString * errorString )
{
Q_UNUSED ( device ) ;
Q_UNUSED ( unit ) ;
* errorString = QStringLiteral ( " Saving code to disk is not supported in this configuration " ) ;
return false ;
}
2016-06-06 14:19:47 +00:00
bool CompilationUnit : : memoryMapCode ( QString * errorString )
{
* errorString = QStringLiteral ( " Missing code mapping backend " ) ;
return false ;
}
2014-03-12 15:55:06 +00:00
# endif // V4_BOOTSTRAP
2014-03-27 16:07:06 +00:00
Unit * CompilationUnit : : createUnitData ( QmlIR : : Document * irDocument )
{
2014-09-24 10:27:21 +00:00
return irDocument - > jsGenerator . generateUnit ( QV4 : : Compiler : : JSUnitGenerator : : GenerateWithoutStringTable ) ;
2014-03-27 16:07:06 +00:00
}
2013-09-13 07:08:41 +00:00
QString Binding : : valueAsString ( const Unit * unit ) const
{
switch ( type ) {
case Type_Script :
case Type_String :
return unit - > stringAt ( stringIndex ) ;
case Type_Boolean :
return value . b ? QStringLiteral ( " true " ) : QStringLiteral ( " false " ) ;
case Type_Number :
2016-07-12 12:19:09 +00:00
return QString : : number ( valueAsNumber ( ) ) ;
2013-09-13 07:08:41 +00:00
case Type_Invalid :
return QString ( ) ;
2014-03-12 15:55:06 +00:00
# ifdef QT_NO_TRANSLATION
case Type_TranslationById :
case Type_Translation :
return unit - > stringAt ( stringIndex ) ;
# else
2014-03-06 15:19:42 +00:00
case Type_TranslationById : {
QByteArray id = unit - > stringAt ( stringIndex ) . toUtf8 ( ) ;
return qtTrId ( id . constData ( ) , value . translationData . number ) ;
}
case Type_Translation : {
// This code must match that in the qsTr() implementation
const QString & path = unit - > stringAt ( unit - > sourceFileIndex ) ;
int lastSlash = path . lastIndexOf ( QLatin1Char ( ' / ' ) ) ;
2016-04-06 12:23:58 +00:00
QStringRef context = ( lastSlash > - 1 ) ? path . midRef ( lastSlash + 1 , path . length ( ) - lastSlash - 5 )
: QStringRef ( ) ;
2014-03-06 15:19:42 +00:00
QByteArray contextUtf8 = context . toUtf8 ( ) ;
QByteArray comment = unit - > stringAt ( value . translationData . commentIndex ) . toUtf8 ( ) ;
QByteArray text = unit - > stringAt ( stringIndex ) . toUtf8 ( ) ;
return QCoreApplication : : translate ( contextUtf8 . constData ( ) , text . constData ( ) ,
comment . constData ( ) , value . translationData . number ) ;
}
2014-03-12 15:55:06 +00:00
# endif
2013-09-13 07:08:41 +00:00
default :
break ;
}
return QString ( ) ;
}
2014-01-10 13:46:33 +00:00
//reverse of Lexer::singleEscape()
2014-08-12 11:52:50 +00:00
QString Binding : : escapedString ( const QString & string )
2014-01-10 13:46:33 +00:00
{
QString tmp = QLatin1String ( " \" " ) ;
for ( int i = 0 ; i < string . length ( ) ; + + i ) {
const QChar & c = string . at ( i ) ;
switch ( c . unicode ( ) ) {
case 0x08 :
tmp + = QLatin1String ( " \\ b " ) ;
break ;
case 0x09 :
tmp + = QLatin1String ( " \\ t " ) ;
break ;
case 0x0A :
tmp + = QLatin1String ( " \\ n " ) ;
break ;
case 0x0B :
tmp + = QLatin1String ( " \\ v " ) ;
break ;
case 0x0C :
tmp + = QLatin1String ( " \\ f " ) ;
break ;
case 0x0D :
tmp + = QLatin1String ( " \\ r " ) ;
break ;
case 0x22 :
tmp + = QLatin1String ( " \\ \" " ) ;
break ;
case 0x27 :
tmp + = QLatin1String ( " \\ \' " ) ;
break ;
case 0x5C :
tmp + = QLatin1String ( " \\ \\ " ) ;
break ;
default :
tmp + = c ;
break ;
}
}
tmp + = QLatin1Char ( ' \" ' ) ;
return tmp ;
}
QString Binding : : valueAsScriptString ( const Unit * unit ) const
{
if ( type = = Type_String )
return escapedString ( unit - > stringAt ( stringIndex ) ) ;
else
return valueAsString ( unit ) ;
}
2016-05-29 17:21:54 +00:00
# ifndef V4_BOOTSTRAP
/*!
Returns the property cache , if one alread exists . The cache is not referenced .
*/
2016-07-28 15:40:29 +00:00
QQmlPropertyCache * ResolvedTypeReference : : propertyCache ( ) const
2016-05-29 17:21:54 +00:00
{
if ( type )
return typePropertyCache ;
else
2016-06-01 10:22:11 +00:00
return compilationUnit - > rootPropertyCache ( ) ;
2016-05-29 17:21:54 +00:00
}
/*!
Returns the property cache , creating one if it doesn ' t already exist . The cache is not referenced .
*/
2016-07-28 15:40:29 +00:00
QQmlPropertyCache * ResolvedTypeReference : : createPropertyCache ( QQmlEngine * engine )
2016-05-29 17:21:54 +00:00
{
if ( typePropertyCache ) {
return typePropertyCache ;
} else if ( type ) {
typePropertyCache = QQmlEnginePrivate : : get ( engine ) - > cache ( type - > metaObject ( ) ) ;
return typePropertyCache ;
} else {
2016-06-01 10:22:11 +00:00
return compilationUnit - > rootPropertyCache ( ) ;
2016-05-29 17:21:54 +00:00
}
}
template < typename T >
bool qtTypeInherits ( const QMetaObject * mo ) {
while ( mo ) {
if ( mo = = & T : : staticMetaObject )
return true ;
mo = mo - > superClass ( ) ;
}
return false ;
}
2016-07-28 15:40:29 +00:00
void ResolvedTypeReference : : doDynamicTypeCheck ( )
2016-05-29 17:21:54 +00:00
{
const QMetaObject * mo = 0 ;
if ( typePropertyCache )
mo = typePropertyCache - > firstCppMetaObject ( ) ;
else if ( type )
mo = type - > metaObject ( ) ;
2016-06-01 10:22:11 +00:00
else if ( compilationUnit )
mo = compilationUnit - > rootPropertyCache ( ) - > firstCppMetaObject ( ) ;
2016-05-29 17:21:54 +00:00
isFullyDynamicType = qtTypeInherits < QQmlPropertyMap > ( mo ) ;
}
2016-07-28 15:40:32 +00:00
bool ResolvedTypeReferenceMap : : addToHash ( QCryptographicHash * hash , QQmlEngine * engine ) const
{
for ( auto it = constBegin ( ) , end = constEnd ( ) ; it ! = end ; + + it ) {
QQmlPropertyCache * pc = it . value ( ) - > createPropertyCache ( engine ) ;
bool ok = false ;
hash - > addData ( pc - > checksum ( & ok ) ) ;
if ( ! ok )
return false ;
}
return true ;
}
2016-05-29 17:21:54 +00:00
# endif
2013-08-14 08:17:31 +00:00
}
}
2013-08-18 13:35:02 +00:00
QT_END_NAMESPACE