diff --git a/bin/qtmodule-configtests b/bin/qtmodule-configtests index 4b4c5ae96c6..d823b372785 100755 --- a/bin/qtmodule-configtests +++ b/bin/qtmodule-configtests @@ -299,10 +299,9 @@ if (abs_path($out_basedir) ne abs_path($qtbasedir)) { # Generate the new contents my $newContents = $existingContents; - # Strip out any existing config test results or include statements + # Strip out any existing config test results $newContents =~ s/^config_test_[^\$]*$//gm; $newContents =~ s/^# Compile time test results[^\$]*$//gm; - $newContents =~ s/include\(\$\$PWD\/..\/.qmake.cache\)$//gm; # Add any remaining content and make sure we start on a new line if ($newContents and chop $newContents ne '\n') { @@ -322,9 +321,6 @@ if (abs_path($out_basedir) ne abs_path($qtbasedir)) { # Remove blank lines $newContents =~ s/^[\s]*$//gms; - # Include top level .qmake.cache - $newContents = $newContents . "include(\$\$PWD/../.qmake.cache)\n"; - # and open the file open my $cacheFileHandle, ">$qmakeCachePath" or die "Unable to open $qmakeCachePath for writing: $!\n"; diff --git a/configure b/configure index 70213fa522e..dc2e4f09571 100755 --- a/configure +++ b/configure @@ -1041,7 +1041,7 @@ while [ "$#" -gt 0 ]; do VAL=no ;; #Qt style yes options - -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-harfbuzz|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu) + -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-harfbuzz|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-v8|-declarative|-declarative-debug|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu) VAR=`echo $1 | sed "s,^-\(.*\),\1,"` VAL=yes ;; @@ -7361,6 +7361,7 @@ fi canBuildQtXmlPatterns="yes" canBuildWebKit="$HAVE_STL" canBuildQtConcurrent="yes" +canBuildV8="yes" # WebKit requires stdint.h "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stdint "Stdint" $L_FLAGS $I_FLAGS $l_FLAGS @@ -7584,8 +7585,18 @@ fi #fi +case "$CFG_ARCH" in +i386|x86_64|arm|macosx) ;; +*) canBuildV8="no";; +esac + +if [ "$CFG_V8" = "yes" -a "$canBuildV8" = "no" ]; then + echo "Error: V8 was requested, but is not supported on this platform." + exit 1 +fi + if [ "$CFG_V8" = "auto" ]; then - CFG_V8=yes + CFG_V8="$canBuildV8" fi if [ "$CFG_V8" = "no" ]; then diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index abe5a825d16..4b05a86d710 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -116,6 +116,9 @@ Qt for Windows CE - moc +* [QTBUG-20785] The moc now has a -b option to #include an additional + file at the beginning of the generated file. + - uic @@ -125,6 +128,9 @@ Qt for Windows CE - qmake +* QMAKE_MOC_OPTIONS variable is now available for passing additional parameters + to the moc. + - configure diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index d0b36e41b2f..64688343191 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -45,10 +45,10 @@ defineReplace(mocCmdBase) { contains(TEMPLATE, "vc.*") { RET += $$mocinclude.commands } - RET += $$QMAKE_MOC $(DEFINES) @$$WIN_INCLUDETEMP $$join(QMAKE_COMPILER_DEFINES, " -D", -D) + RET += $$QMAKE_MOC $(DEFINES) @$$WIN_INCLUDETEMP $$join(QMAKE_COMPILER_DEFINES, " -D", -D) $$QMAKE_MOC_OPTIONS return($$RET) } - return($$QMAKE_MOC $(DEFINES) $(INCPATH) $$join(QMAKE_COMPILER_DEFINES, " -D", -D)) + return($$QMAKE_MOC $(DEFINES) $(INCPATH) $$join(QMAKE_COMPILER_DEFINES, " -D", -D) $$QMAKE_MOC_OPTIONS) } #moc headers diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index f50afc36849..0b201b87234 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -1524,8 +1524,8 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool) { xml << tag(tool.EventName) - << attrTagS(_Command, tool.CommandLine.join(vcxCommandSeparator())) - << attrTagS(_Message, tool.Description) + << tag(_Command) << valueTag(tool.CommandLine.join(vcxCommandSeparator())) + << tag(_Message) << valueTag(tool.Description) << closetag(tool.EventName); } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c56c050f768..3a2e35c322f 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3535,6 +3535,61 @@ bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const } +#if defined(QT_ALWAYS_HAVE_SSE2) +static inline __m128i mergeQuestionMarks(__m128i chunk) +{ + const __m128i questionMark = _mm_set1_epi16('?'); + +# ifdef __SSE4_2__ + // compare the unsigned shorts for the range 0x0100-0xFFFF + // note on the use of _mm_cmpestrm: + // The MSDN documentation online (http://technet.microsoft.com/en-us/library/bb514080.aspx) + // says for range search the following: + // For each character c in a, determine whether b0 <= c <= b1 or b2 <= c <= b3 + // + // However, all examples on the Internet, including from Intel + // (see http://software.intel.com/en-us/articles/xml-parsing-accelerator-with-intel-streaming-simd-extensions-4-intel-sse4/) + // put the range to be searched first + // + // Disassembly and instruction-level debugging with GCC and ICC show + // that they are doing the right thing. Inverting the arguments in the + // instruction does cause a bunch of test failures. + + const int mode = _SIDD_UWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK; + const __m128i rangeMatch = _mm_cvtsi32_si128(0xffff0100); + const __m128i offLimitMask = _mm_cmpestrm(rangeMatch, 2, chunk, 8, mode); + + // replace the non-Latin 1 characters in the chunk with question marks + chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask); +# else + // SSE has no compare instruction for unsigned comparison. + // The variables must be shiffted + 0x8000 to be compared + const __m128i signedBitOffset = _mm_set1_epi16(0x8000); + const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000); + + const __m128i signedChunk = _mm_add_epi16(chunk, signedBitOffset); + const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask); + +# ifdef __SSE4_1__ + // replace the non-Latin 1 characters in the chunk with question marks + chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask); +# else + // offLimitQuestionMark contains '?' for each 16 bits that was off-limit + // the 16 bits that were correct contains zeros + const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark); + + // correctBytes contains the bytes that were in limit + // the 16 bits that were off limits contains zeros + const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk); + + // merge offLimitQuestionMark and correctBytes to have the result + chunk = _mm_or_si128(correctBytes, offLimitQuestionMark); +# endif +# endif + return chunk; +} +#endif + static QByteArray toLatin1_helper(const QChar *data, int length) { QByteArray ba; @@ -3545,41 +3600,15 @@ static QByteArray toLatin1_helper(const QChar *data, int length) #if defined(QT_ALWAYS_HAVE_SSE2) if (length >= 16) { const int chunkCount = length >> 4; // divided by 16 - const __m128i questionMark = _mm_set1_epi16('?'); - // SSE has no compare instruction for unsigned comparison. - // The variables must be shiffted + 0x8000 to be compared - const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000)); - const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000)); + for (int i = 0; i < chunkCount; ++i) { __m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load + chunk1 = mergeQuestionMarks(chunk1); src += 8; - { - // each 16 bit is equal to 0xFF if the source is outside latin 1 (>0xff) - const __m128i signedChunk = _mm_add_epi16(chunk1, signedBitOffset); - const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask); - - // offLimitQuestionMark contains '?' for each 16 bits that was off-limit - // the 16 bits that were correct contains zeros - const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark); - - // correctBytes contains the bytes that were in limit - // the 16 bits that were off limits contains zeros - const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk1); - - // merge offLimitQuestionMark and correctBytes to have the result - chunk1 = _mm_or_si128(correctBytes, offLimitQuestionMark); - } __m128i chunk2 = _mm_loadu_si128((__m128i*)src); // load + chunk2 = mergeQuestionMarks(chunk2); src += 8; - { - // exactly the same operations as for the previous chunk of data - const __m128i signedChunk = _mm_add_epi16(chunk2, signedBitOffset); - const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask); - const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark); - const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk2); - chunk2 = _mm_or_si128(correctBytes, offLimitQuestionMark); - } // pack the two vector to 16 x 8bits elements const __m128i result = _mm_packus_epi16(chunk1, chunk2); diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index fa97ccb78cb..dd0be205d82 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -901,15 +901,38 @@ static const char *certificate_blacklist[] = { "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", "addons.mozilla.org", // Comodo "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", "login.live.com", // Comodo "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", "global trustee", // Comodo - "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", // DigiNotar + + "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", // leaf certificate issued by DigiNotar + "0c:76:da:9c:91:0c:4e:2c:9e:fe:15:d0:58:93:3c:4c", "DigiNotar Root CA", // DigiNotar root + "f1:4a:13:f4:87:2b:56:dc:39:df:84:ca:7a:a1:06:49", "DigiNotar Services CA", // DigiNotar intermediate signed by DigiNotar Root + "36:16:71:55:43:42:1b:9d:e6:cb:a3:64:41:df:24:38", "DigiNotar Services 1024 CA", // DigiNotar intermediate signed by DigiNotar Root + "0a:82:bd:1e:14:4e:88:14:d7:5b:1a:55:27:be:bf:3e", "DigiNotar Root CA G2", // other DigiNotar Root CA + "a4:b6:ce:e3:2e:d3:35:46:26:3c:b3:55:3a:a8:92:21", "CertiID Enterprise Certificate Authority", // DigiNotar intermediate signed by "DigiNotar Root CA G2" + "5b:d5:60:9c:64:17:68:cf:21:0e:35:fd:fb:05:ad:41", "DigiNotar Qualified CA", // DigiNotar intermediate signed by DigiNotar Root + + "1184640176", "DigiNotar Services 1024 CA", // DigiNotar intermediate cross-signed by Entrust + "120000525", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust + "120000505", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust + "120000515", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust + "20015536", "DigiNotar PKIoverheid CA Overheid en Bedrijven", // DigiNotar intermediate cross-signed by the Dutch government + "20001983", "DigiNotar PKIoverheid CA Organisatie - G2", // DigiNotar intermediate cross-signed by the Dutch government + "d6:d0:29:77:f1:49:fd:1a:83:f2:b9:ea:94:8c:5c:b4", "DigiNotar Extended Validation CA", // DigiNotar intermediate signed by DigiNotar EV Root + "1e:7d:7a:53:3d:45:30:41:96:40:0f:71:48:1f:45:04", "DigiNotar Public CA 2025", // DigiNotar intermediate +// "(has not been seen in the wild so far)", "DigiNotar Public CA - G2", // DigiNotar intermediate +// "(has not been seen in the wild so far)", "Koninklijke Notariele Beroepsorganisatie CA", // compromised during DigiNotar breach +// "(has not been seen in the wild so far)", "Stichting TTP Infos CA," // compromised during DigiNotar breach + "1184640175", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust + "1184644297", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust 0 }; bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) { for (int a = 0; certificate_blacklist[a] != 0; a++) { + QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]); if (certificate.serialNumber() == certificate_blacklist[a++] && - certificate.subjectInfo(QSslCertificate::CommonName).contains(QString::fromUtf8(certificate_blacklist[a]))) + (certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) || + certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName))) return true; } return false; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 0ff17910f33..14a3899bfdd 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1270,12 +1270,15 @@ bool QSslSocketBackendPrivate::startHandshake() // Start translating errors. QList errors; - if (QSslCertificatePrivate::isBlacklisted(configuration.peerCertificate)) { - QSslError error(QSslError::CertificateBlacklisted, configuration.peerCertificate); - errors << error; - emit q->peerVerifyError(error); - if (q->state() != QAbstractSocket::ConnectedState) - return false; + // check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer) + foreach (const QSslCertificate &cert, configuration.peerCertificateChain) { + if (QSslCertificatePrivate::isBlacklisted(cert)) { + QSslError error(QSslError::CertificateBlacklisted, cert); + errors << error; + emit q->peerVerifyError(error); + if (q->state() != QAbstractSocket::ConnectedState) + return false; + } } bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index d506d7c0f84..9726ad81199 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -475,14 +475,14 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: fid.filename = fontfile->fileName.toLocal8Bit(); fid.index = fontfile->indexValue; - //try and get the pattern - FcPattern *pattern = FcPatternCreate(); - bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; engine = new QFontEngineFT(fontDef); + // try and get the pattern + FcPattern *pattern = FcPatternCreate(); + FcValue value; value.type = FcTypeString; QByteArray cs = fontDef.family.toUtf8(); @@ -497,9 +497,8 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: value.u.i = fid.index; FcPatternAdd(pattern,FC_INDEX,value,true); - QFontEngineFT::HintStyle default_hint_style; - if (FcConfigSubstitute(0,pattern,FcMatchPattern)) { + QFontEngineFT::HintStyle default_hint_style; //hinting int hint_style = 0; @@ -519,9 +518,10 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: default_hint_style = QFontEngineFT::HintFull; break; } + engine->setDefaultHintStyle(default_hint_style); } + FcPatternDestroy(pattern); - engine->setDefaultHintStyle(default_hint_style); if (!engine->init(fid,antialias,format)) { delete engine; engine = 0; @@ -576,26 +576,29 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const } FcConfigSubstitute(0, pattern, FcMatchPattern); - FcConfigSubstitute(0, pattern, FcMatchFont); + FcDefaultSubstitute(pattern); FcResult result = FcResultMatch; FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); + FcPatternDestroy(pattern); - if (fontSet && result == FcResultMatch) - { - for (int i = 0; i < fontSet->nfont; i++) { - FcChar8 *value = 0; - if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) - continue; - // capitalize(value); - QString familyName = QString::fromUtf8((const char *)value); - if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive)) { - fallbackFamilies << familyName; + if (fontSet) { + if (result == FcResultMatch) { + for (int i = 0; i < fontSet->nfont; i++) { + FcChar8 *value = 0; + if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + QString familyName = QString::fromUtf8((const char *)value); + if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) && + familyName.compare(family, Qt::CaseInsensitive)) { + fallbackFamilies << familyName; + } } - } + FcFontSetDestroy(fontSet); } -// qDebug() << "fallbackFamilies for:" << family << fallbackFamilies; +// qDebug() << "fallbackFamilies for:" << family << style << styleHint << script << fallbackFamilies; return fallbackFamilies; } diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index eaafd0a9fdd..bf7e22c0b95 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -83,7 +83,8 @@ void error(const char *msg = "Invalid argument") " -U undefine macro\n" " -i do not generate an #include statement\n" " -p path prefix for included file\n" - " -f[] force #include, optional file name\n" + " -f[] force #include, optional file name (overwrite default)\n" + " -b prepend #include (preserve default include)\n" " -nn do not display notes\n" " -nw do not display warnings\n" " @ read additional options from file\n" @@ -156,6 +157,7 @@ QByteArray composePreprocessorOutput(const Symbols &symbols) { int runMoc(int _argc, char **_argv) { bool autoInclude = true; + bool defaultInclude = true; Preprocessor pp; Moc moc; pp.macros["Q_MOC_RUN"]; @@ -226,8 +228,21 @@ int runMoc(int _argc, char **_argv) break; moc.noInclude = false; autoInclude = false; - if (opt[1]) // -fsomething.h + if (opt[1]) { // -fsomething.h moc.includeFiles.append(opt.mid(1)); + defaultInclude = false; + } + break; + case 'b': + if (ignoreConflictingOptions) + break; + if (!more) { + if (!(n < argc-1)) + error("Missing file name for the -b option."); + moc.includeFiles.prepend(argv[++n]); + } else if (opt[1]) { + moc.includeFiles.prepend(opt.mid(1)); + } break; case 'p': // include file path if (ignoreConflictingOptions) @@ -341,7 +356,7 @@ int runMoc(int _argc, char **_argv) // spos >= -1 && ppos > spos => ppos >= 0 moc.noInclude = (ppos > spos && tolower(filename[ppos + 1]) != 'h'); } - if (moc.includeFiles.isEmpty()) { + if (defaultInclude) { if (moc.includePath.isEmpty()) { if (filename.size()) { if (output.size()) diff --git a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch index 4ec44e35478..fefdd79baa3 100644 --- a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch +++ b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch @@ -1,27 +1,27 @@ -From e13ce09287a56c920d5ffdc5d4662d49f1838f16 Mon Sep 17 00:00:00 2001 +From 3dff2e903674d8ab5310d44281b57de36db659c9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 23 May 2011 15:47:20 +1000 -Subject: [PATCH 01/16] Add hashing and comparison methods to v8::String +Subject: [PATCH 01/15] Add hashing and comparison methods to v8::String This allows us to more rapidly search for a v8::String inside a hash of QStrings. --- - include/v8.h | 44 ++++++++++++++++++++++++++++++ + include/v8.h | 45 +++++++++++++++++++++++++++++++ src/api.cc | 43 +++++++++++++++++++++++++++++ src/heap-inl.h | 2 + src/heap.cc | 3 ++ src/objects-inl.h | 1 + src/objects.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/objects.h | 15 +++++++++- - 7 files changed, 182 insertions(+), 3 deletions(-) + 7 files changed, 183 insertions(+), 3 deletions(-) diff --git a/include/v8.h b/include/v8.h -index d15d024..bbd29e9 100644 +index d15d024..be1ee71 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -994,6 +994,48 @@ class String : public Primitive { +@@ -994,6 +994,49 @@ class String : public Primitive { V8EXPORT int Utf8Length() const; - + /** + * Returns the hash of this string. + */ @@ -35,7 +35,7 @@ index d15d024..bbd29e9 100644 + }; + + /** -+ * Returns the "complete" hash of the string. This is ++ * Returns the "complete" hash of the string. This is + * all the information about the string needed to implement + * a very efficient hash keyed on the string. + * @@ -43,7 +43,7 @@ index d15d024..bbd29e9 100644 + * length: The length of the string. Equivalent to Length() + * hash: The hash of the string. Equivalent to Hash() + * symbol_id: If the string is a sequential symbol, the symbol -+ * id, otherwise 0. If the symbol ids of two strings are ++ * id, otherwise 0. If the symbol ids of two strings are + * the same (and non-zero) the two strings are identical. + * If the symbol ids are different the strings may still be + * identical, but an Equals() check must be performed. @@ -63,15 +63,16 @@ index d15d024..bbd29e9 100644 + */ + V8EXPORT bool Equals(uint16_t *string, int length); + V8EXPORT bool Equals(char *string, int length); ++ inline bool Equals(Handle that) const { return v8::Value::Equals(that); } + + /** * Write the contents of the string to an external buffer. * If no arguments are given, expects the buffer to be large * enough to hold the entire string and NULL terminator. Copies -@@ -1023,6 +1065,8 @@ class String : public Primitive { +@@ -1023,6 +1066,8 @@ class String : public Primitive { HINT_MANY_WRITES_EXPECTED = 1 }; - + + V8EXPORT uint16_t GetCharacter(int index); + V8EXPORT int Write(uint16_t* buffer, @@ -84,7 +85,7 @@ index a2373cd..381935b 100644 @@ -3284,6 +3284,49 @@ int String::Utf8Length() const { return str->Utf8Length(); } - + +uint32_t String::Hash() const { + i::Handle str = Utils::OpenHandle(this); + if (IsDeadCheck(str->GetIsolate(), "v8::String::Hash()")) return 0; @@ -128,7 +129,7 @@ index a2373cd..381935b 100644 + if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; + return str->SlowEqualsExternal(string, length); +} - + int String::WriteUtf8(char* buffer, int capacity, diff --git a/src/heap-inl.h b/src/heap-inl.h @@ -140,17 +141,17 @@ index 99737ed..f4fce7b 100644 answer->set_length(str.length()); answer->set_hash_field(hash_field); + SeqString::cast(answer)->set_symbol_id(0); - + ASSERT_EQ(size, answer->Size()); - + @@ -126,6 +127,7 @@ MaybeObject* Heap::AllocateTwoByteSymbol(Vector str, String* answer = String::cast(result); answer->set_length(str.length()); answer->set_hash_field(hash_field); + SeqString::cast(answer)->set_symbol_id(0); - + ASSERT_EQ(size, answer->Size()); - + diff --git a/src/heap.cc b/src/heap.cc index 2b6c11f..930c97b 100644 --- a/src/heap.cc @@ -160,9 +161,9 @@ index 2b6c11f..930c97b 100644 answer->set_length(chars); answer->set_hash_field(hash_field); + SeqString::cast(result)->set_symbol_id(0); - + ASSERT_EQ(size, answer->Size()); - + @@ -3561,6 +3562,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { HeapObject::cast(result)->set_map(ascii_string_map()); String::cast(result)->set_length(length); @@ -184,12 +185,12 @@ index 65aec5d..c82080d 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset) - - + + SMI_ACCESSORS(String, length, kLengthOffset) +SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset) - - + + uint32_t String::hash_field() { diff --git a/src/objects.cc b/src/objects.cc index df61956..dc4b260 100644 @@ -198,7 +199,7 @@ index df61956..dc4b260 100644 @@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, } } - + +bool String::SlowEqualsExternal(uc16 *string, int length) { + int len = this->length(); + if (len != length) return false; @@ -259,11 +260,11 @@ index df61956..dc4b260 100644 + return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib); + } +} - + bool String::SlowEquals(String* other) { // Fast check: negative check with lengths. @@ -8655,9 +8715,24 @@ class AsciiSymbolKey : public SequentialSymbolKey { - + MaybeObject* AsObject() { if (hash_field_ == 0) Hash(); - return HEAP->AllocateAsciiSymbol(string_, hash_field_); @@ -285,8 +286,8 @@ index df61956..dc4b260 100644 + static Atomic32 next_symbol_id; }; +Atomic32 AsciiSymbolKey::next_symbol_id = 1; - - + + class TwoByteSymbolKey : public SequentialSymbolKey { diff --git a/src/objects.h b/src/objects.h index e966b3d..6e26f57 100644 @@ -295,7 +296,7 @@ index e966b3d..6e26f57 100644 @@ -5359,6 +5359,9 @@ class String: public HeapObject { bool IsAsciiEqualTo(Vector str); bool IsTwoByteEqualTo(Vector str); - + + bool SlowEqualsExternal(uc16 *string, int length); + bool SlowEqualsExternal(char *string, int length); + @@ -305,14 +306,14 @@ index e966b3d..6e26f57 100644 @@ -5610,9 +5613,17 @@ class String: public HeapObject { class SeqString: public String { public: - + + // Get and set the symbol id of the string + inline int symbol_id(); + inline void set_symbol_id(int value); + // Casting. static inline SeqString* cast(Object* obj); - + + // Layout description. + static const int kSymbolIdOffset = String::kSize; + static const int kSize = kSymbolIdOffset + kPointerSize; @@ -322,22 +323,22 @@ index e966b3d..6e26f57 100644 }; @@ -5647,7 +5658,7 @@ class SeqAsciiString: public SeqString { } - + // Layout description. - static const int kHeaderSize = String::kSize; + static const int kHeaderSize = SeqString::kSize; static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); - + // Maximal memory usage for a single sequential ASCII string. @@ -5701,7 +5712,7 @@ class SeqTwoByteString: public SeqString { } - + // Layout description. - static const int kHeaderSize = String::kSize; + static const int kHeaderSize = SeqString::kSize; static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); - + // Maximal memory usage for a single sequential two-byte string. --- -1.7.6 +-- +1.7.4.4 diff --git a/src/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/v8/0002-Add-a-bit-field-3-to-Map.patch index 4b21317668d..71240210290 100644 --- a/src/v8/0002-Add-a-bit-field-3-to-Map.patch +++ b/src/v8/0002-Add-a-bit-field-3-to-Map.patch @@ -1,7 +1,7 @@ -From 7c9cfff80b7864d5687432d424074e51712c4a07 Mon Sep 17 00:00:00 2001 +From 01f7bd262fb1be893fe4bdc6b98a1b43c5a0bb7d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 23 May 2011 15:55:26 +1000 -Subject: [PATCH 02/16] Add a bit field 3 to Map +Subject: [PATCH 02/15] Add a bit field 3 to Map Bit field 3 will be used to add QML specific map flags. --- @@ -22,13 +22,13 @@ index 930c97b..900f462 100644 + reinterpret_cast(result)->set_bit_field3(0); return result; } - + @@ -1599,6 +1600,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { map->set_unused_property_fields(0); map->set_bit_field(0); map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); + map->set_bit_field3(0); - + // If the map object is aligned fill the padding area with Smi 0 objects. if (Map::kPadStart < Map::kSize) { diff --git a/src/objects-inl.h b/src/objects-inl.h @@ -37,8 +37,8 @@ index c82080d..cce3edd 100644 +++ b/src/objects-inl.h @@ -2430,6 +2430,16 @@ void Map::set_bit_field2(byte value) { } - - + + +byte Map::bit_field3() { + return READ_BYTE_FIELD(this, kBitField3Offset); +} @@ -65,13 +65,13 @@ index dc4b260..79d7240 100644 Map::cast(result)->ClearCodeCache(heap); return result; @@ -3642,6 +3643,7 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, - + Map::cast(result)->set_bit_field(bit_field()); Map::cast(result)->set_bit_field2(bit_field2()); + Map::cast(result)->set_bit_field3(bit_field3()); - + Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); - + diff --git a/src/objects.h b/src/objects.h index 6e26f57..07e1089 100644 --- a/src/objects.h @@ -79,7 +79,7 @@ index 6e26f57..07e1089 100644 @@ -3597,6 +3597,10 @@ class Map: public HeapObject { inline byte bit_field2(); inline void set_bit_field2(byte value); - + + // Bit field 3. + inline byte bit_field3(); + inline void set_bit_field3(byte value); @@ -101,18 +101,18 @@ index 6e26f57..07e1089 100644 static const int kBitFieldOffset = kInstanceAttributesOffset + 2; static const int kBitField2Offset = kInstanceAttributesOffset + 3; + static const int kBitField3Offset = kInstanceAttributesOffset + 4; - + STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); - + @@ -3898,6 +3903,8 @@ class Map: public HeapObject { static const int kIsShared = 5; static const int kHasExternalArrayElements = 6; - + + // Bit positions for bit field 3 + // Layout of the default cache. It holds alternating name and code objects. static const int kCodeCacheEntrySize = 2; static const int kCodeCacheEntryNameOffset = 0; --- -1.7.6 +-- +1.7.4.4 diff --git a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch index 27529ff3daa..5c80fcf4b8a 100644 --- a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch +++ b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch @@ -1,7 +1,7 @@ -From ae8688b53d67044f2c9b0cce25fc282b078610c1 Mon Sep 17 00:00:00 2001 +From 530ded6ea634bccb96652cd3e0cf67725449ed63 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 23 May 2011 16:21:02 +1000 -Subject: [PATCH 03/16] Add a "fallback" mode for named property interceptors +Subject: [PATCH 03/15] Add a "fallback" mode for named property interceptors By default interceptors are called before the normal property resolution on objects. When an interceptor is installed as a @@ -24,10 +24,10 @@ declarations. 9 files changed, 99 insertions(+), 18 deletions(-) diff --git a/include/v8.h b/include/v8.h -index bbd29e9..85452aa 100644 +index be1ee71..bb31ea0 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -2169,6 +2169,7 @@ class V8EXPORT FunctionTemplate : public Template { +@@ -2170,6 +2170,7 @@ class V8EXPORT FunctionTemplate : public Template { NamedPropertyQuery query, NamedPropertyDeleter remover, NamedPropertyEnumerator enumerator, @@ -35,10 +35,10 @@ index bbd29e9..85452aa 100644 Handle data); void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, IndexedPropertySetter setter, -@@ -2253,6 +2254,13 @@ class V8EXPORT ObjectTemplate : public Template { +@@ -2254,6 +2255,13 @@ class V8EXPORT ObjectTemplate : public Template { NamedPropertyEnumerator enumerator = 0, Handle data = Handle()); - + + void SetFallbackPropertyHandler(NamedPropertyGetter getter, + NamedPropertySetter setter = 0, + NamedPropertyQuery query = 0, @@ -66,7 +66,7 @@ index 381935b..8b0b32a 100644 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); + obj->set_is_fallback(i::Smi::FromInt(is_fallback)); - + if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); @@ -1143,6 +1145,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, @@ -102,7 +102,7 @@ index 381935b..8b0b32a 100644 + true, data); } - + diff --git a/src/factory.cc b/src/factory.cc index 7dee66f..dcdc645 100644 --- a/src/factory.cc @@ -131,11 +131,11 @@ index 326de86..dd3a86c 100644 + bool skip_fallback_interceptor) { CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetProperty(*key, *value, attributes, strict_mode), -+ object->SetProperty(*key, *value, attributes, strict_mode, ++ object->SetProperty(*key, *value, attributes, strict_mode, + skip_fallback_interceptor), Object); } - + diff --git a/src/handles.h b/src/handles.h index 3839f37..4b42506 100644 --- a/src/handles.h @@ -147,7 +147,7 @@ index 3839f37..4b42506 100644 - StrictModeFlag strict_mode); + StrictModeFlag strict_mode, + bool skip_fallback_interceptor = false); - + Handle SetProperty(Handle object, Handle key, diff --git a/src/objects-inl.h b/src/objects-inl.h @@ -156,8 +156,8 @@ index cce3edd..6aaca2f 100644 +++ b/src/objects-inl.h @@ -2521,6 +2521,21 @@ bool Map::is_shared() { } - - + + +void Map::set_named_interceptor_is_fallback(bool value) +{ + if (value) { @@ -181,7 +181,7 @@ index cce3edd..6aaca2f 100644 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) ACCESSORS(InterceptorInfo, data, Object, kDataOffset) +ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset) - + ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) diff --git a/src/objects.cc b/src/objects.cc @@ -200,20 +200,20 @@ index 79d7240..15e2cdb 100644 + LocalLookup(name, &result, skip_fallback_interceptor); return SetProperty(&result, name, value, attributes, strict_mode); } - + @@ -3148,7 +3149,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { } - - + + -void JSObject::LocalLookup(String* name, LookupResult* result) { +void JSObject::LocalLookup(String* name, LookupResult* result, + bool skip_fallback_interceptor) { ASSERT(name->IsString()); - + Heap* heap = GetHeap(); @@ -3174,22 +3176,30 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { } - + // Check for lookup interceptor except when bootstrapping. - if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { + bool wouldIntercept = HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive(); @@ -221,19 +221,19 @@ index 79d7240..15e2cdb 100644 result->InterceptorResult(this); return; } - + LocalLookupRealNamedProperty(name, result); + -+ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && ++ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && + map()->named_interceptor_is_fallback()) { + result->InterceptorResult(this); + return; + } } - - + + -void JSObject::Lookup(String* name, LookupResult* result) { -+void JSObject::Lookup(String* name, LookupResult* result, ++void JSObject::Lookup(String* name, LookupResult* result, + bool skip_fallback_interceptor) { // Ecma-262 3rd 8.6.2.4 Heap* heap = GetHeap(); @@ -260,21 +260,21 @@ index 07e1089..a209cd0 100644 String* key, Object* value, @@ -1637,8 +1638,8 @@ class JSObject: public HeapObject { - + // Lookup a property. If found, the result is valid and has // detailed information. - void LocalLookup(String* name, LookupResult* result); - void Lookup(String* name, LookupResult* result); + void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); + void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); - + // The following lookup functions skip interceptors. void LocalLookupRealNamedProperty(String* name, LookupResult* result); @@ -3714,6 +3715,12 @@ class Map: public HeapObject { inline void set_is_access_check_needed(bool access_check_needed); inline bool is_access_check_needed(); - -+ + ++ + // Whether the named interceptor is a fallback interceptor or not + inline void set_named_interceptor_is_fallback(bool value); + inline bool named_interceptor_is_fallback(); @@ -282,13 +282,13 @@ index 07e1089..a209cd0 100644 + // [prototype]: implicit prototype object. DECL_ACCESSORS(prototype, Object) - + @@ -3904,6 +3911,7 @@ class Map: public HeapObject { static const int kHasExternalArrayElements = 6; - + // Bit positions for bit field 3 + static const int kNamedInterceptorIsFallback = 0; - + // Layout of the default cache. It holds alternating name and code objects. static const int kCodeCacheEntrySize = 2; @@ -6276,6 +6284,7 @@ class InterceptorInfo: public Struct { @@ -296,9 +296,9 @@ index 07e1089..a209cd0 100644 DECL_ACCESSORS(enumerator, Object) DECL_ACCESSORS(data, Object) + DECL_ACCESSORS(is_fallback, Smi) - + static inline InterceptorInfo* cast(Object* obj); - + @@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct { static const int kDeleterOffset = kQueryOffset + kPointerSize; static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; @@ -306,7 +306,7 @@ index 07e1089..a209cd0 100644 - static const int kSize = kDataOffset + kPointerSize; + static const int kFallbackOffset = kDataOffset + kPointerSize; + static const int kSize = kFallbackOffset + kPointerSize; - + private: DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); diff --git a/src/runtime.cc b/src/runtime.cc @@ -324,11 +324,11 @@ index 7335da8..660352c 100644 // against the global object. The information will be used to @@ -1152,7 +1152,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { } - + LookupResult lookup; - global->LocalLookup(*name, &lookup); + global->LocalLookup(*name, &lookup, true); - + PropertyAttributes attributes = is_const_property ? static_cast(base | READ_ONLY) @@ -1196,7 +1196,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { @@ -340,7 +340,7 @@ index 7335da8..660352c 100644 + true)); } } - + @@ -1343,7 +1344,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { JSObject* real_holder = global; LookupResult lookup; @@ -351,7 +351,7 @@ index 7335da8..660352c 100644 // Determine if this is a redeclaration of something read-only. if (lookup.IsReadOnly()) { @@ -1400,7 +1401,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - + global = isolate->context()->global(); if (assign) { - return global->SetProperty(*name, args[2], attributes, strict_mode); @@ -359,6 +359,6 @@ index 7335da8..660352c 100644 } return isolate->heap()->undefined_value(); } --- -1.7.6 +-- +1.7.4.4 diff --git a/src/v8/0004-Generalize-external-object-resources.patch b/src/v8/0004-Generalize-external-object-resources.patch index a05aad08890..004380168d9 100644 --- a/src/v8/0004-Generalize-external-object-resources.patch +++ b/src/v8/0004-Generalize-external-object-resources.patch @@ -1,7 +1,7 @@ -From 4827116b12c50f6662794017c5a662b5dbb2da0b Mon Sep 17 00:00:00 2001 +From f9368b52060c31e9532ef26f6cca1a2cb0283f51 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 23 May 2011 16:55:35 +1000 -Subject: [PATCH 04/16] Generalize external object resources +Subject: [PATCH 04/15] Generalize external object resources V8 was already able to manage and finalize an external string resource. This change generalizes that mechanism to handle a @@ -31,13 +31,13 @@ object space. 11 files changed, 280 insertions(+), 115 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 85452aa..7f06ae7 100644 +index bb31ea0..205e856 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -1630,6 +1630,25 @@ class Object : public Value { +@@ -1631,6 +1631,25 @@ class Object : public Value { /** Sets a native pointer in an internal field. */ V8EXPORT void SetPointerInInternalField(int index, void* value); - + + class V8EXPORT ExternalResource { // NOLINT + public: + ExternalResource() {} @@ -60,10 +60,10 @@ index 85452aa..7f06ae7 100644 // Testers for local properties. V8EXPORT bool HasRealNamedProperty(Handle key); V8EXPORT bool HasRealIndexedProperty(uint32_t index); -@@ -2331,6 +2350,12 @@ class V8EXPORT ObjectTemplate : public Template { +@@ -2332,6 +2351,12 @@ class V8EXPORT ObjectTemplate : public Template { */ void SetInternalFieldCount(int value); - + + /** + * Sets whether the object can store an "external resource" object. + */ @@ -79,8 +79,8 @@ index 8b0b32a..1a6fbbb 100644 +++ b/src/api.cc @@ -1294,6 +1294,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) { } - - + + +bool ObjectTemplate::HasExternalResource() +{ + if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(), @@ -110,12 +110,12 @@ index 8b0b32a..1a6fbbb 100644 + + // --- S c r i p t D a t a --- - - + + @@ -3652,6 +3680,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { } - - + + +void v8::Object::SetExternalResource(v8::Object::ExternalResource *resource) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + ENTER_V8(isolate); @@ -145,8 +145,8 @@ index 8b0b32a..1a6fbbb 100644 + + // --- E n v i r o n m e n t --- - - + + @@ -4144,7 +4200,7 @@ Local v8::String::NewExternal( LOG_API(isolate, "String::NewExternal"); ENTER_V8(isolate); @@ -155,7 +155,7 @@ index 8b0b32a..1a6fbbb 100644 + isolate->heap()->external_resource_table()->AddString(*result); return Utils::ToLocal(result); } - + @@ -4162,7 +4218,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { } bool result = obj->MakeExternal(resource); @@ -173,7 +173,7 @@ index 8b0b32a..1a6fbbb 100644 + isolate->heap()->external_resource_table()->AddString(*result); return Utils::ToLocal(result); } - + @@ -4194,7 +4250,7 @@ bool v8::String::MakeExternal( } bool result = obj->MakeExternal(resource); @@ -211,7 +211,7 @@ index dcdc645..d530a75 100644 +++ b/src/factory.cc @@ -997,15 +997,21 @@ Handle Factory::CreateApiFunction( Handle construct_stub = isolate()->builtins()->JSConstructStubApi(); - + int internal_field_count = 0; + bool has_external_resource = false; + @@ -224,7 +224,7 @@ index dcdc645..d530a75 100644 + has_external_resource = + !instance_template->has_external_resource()->IsUndefined(); } - + int instance_size = kPointerSize * internal_field_count; + if (has_external_resource) instance_size += kPointerSize; + @@ -232,9 +232,9 @@ index dcdc645..d530a75 100644 switch (instance_type) { case JavaScriptObject: @@ -1040,6 +1046,11 @@ Handle Factory::CreateApiFunction( - + Handle map = Handle(result->initial_map()); - + + // Mark as having external data object if needed + if (has_external_resource) { + map->set_has_external_resource(true); @@ -249,8 +249,8 @@ index f4fce7b..58e7adf 100644 +++ b/src/heap-inl.h @@ -205,21 +205,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) { } - - + + -void Heap::FinalizeExternalString(String* string) { - ASSERT(string->IsExternalString()); - v8::String::ExternalStringResourceBase** resource_addr = @@ -277,7 +277,7 @@ index f4fce7b..58e7adf 100644 + if (*resource_addr != NULL) { + (*resource_addr)->Dispose(); + } - + - // Clear the resource pointer in the string. - *resource_addr = NULL; + // Clear the resource pointer in the string. @@ -290,18 +290,18 @@ index f4fce7b..58e7adf 100644 + resource = reinterpret_cast(Internals::GetExternalPointerFromSmi(value)); + } else if (value->IsProxy()) { + resource = reinterpret_cast(Proxy::cast(value)->proxy()); -+ } ++ } + if (resource) { + resource->Dispose(); + } + } } - - + + @@ -556,53 +571,63 @@ inline bool Heap::allow_allocation(bool new_state) { #endif - - + + -void ExternalStringTable::AddString(String* string) { - ASSERT(string->IsExternalString()); +void ExternalResourceTable::AddString(String* string) { @@ -324,8 +324,8 @@ index f4fce7b..58e7adf 100644 + old_space_objects_.Add(object); } } - - + + -void ExternalStringTable::Iterate(ObjectVisitor* v) { - if (!new_space_strings_.is_empty()) { - Object** start = &new_space_strings_[0]; @@ -343,8 +343,8 @@ index f4fce7b..58e7adf 100644 + v->VisitPointers(start, start + old_space_objects_.length()); } } - - + + // Verify() is inline to avoid ifdef-s around its calls in release // mode. -void ExternalStringTable::Verify() { @@ -366,8 +366,8 @@ index f4fce7b..58e7adf 100644 } #endif } - - + + -void ExternalStringTable::AddOldString(String* string) { - ASSERT(string->IsExternalString()); - ASSERT(!heap_->InNewSpace(string)); @@ -377,15 +377,15 @@ index f4fce7b..58e7adf 100644 + ASSERT(!heap_->InNewSpace(object)); + old_space_objects_.Add(object); } - - + + -void ExternalStringTable::ShrinkNewStrings(int position) { - new_space_strings_.Rewind(position); +void ExternalResourceTable::ShrinkNewObjects(int position) { + new_space_objects_.Rewind(position); Verify(); } - + diff --git a/src/heap.cc b/src/heap.cc index 900f462..bf2940e 100644 --- a/src/heap.cc @@ -397,68 +397,68 @@ index 900f462..bf2940e 100644 - external_string_table_.heap_ = this; + external_resource_table_.heap_ = this; } - - + + @@ -1030,8 +1030,8 @@ void Heap::Scavenge() { - + new_space_front = DoScavenge(&scavenge_visitor, new_space_front); - + - UpdateNewSpaceReferencesInExternalStringTable( - &UpdateNewSpaceReferenceInExternalStringTableEntry); + UpdateNewSpaceReferencesInExternalResourceTable( + &UpdateNewSpaceReferenceInExternalResourceTableEntry); - + LiveObjectList::UpdateReferencesForScavengeGC(); isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); @@ -1053,38 +1053,38 @@ void Heap::Scavenge() { } - - + + -String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, - Object** p) { +HeapObject* Heap::UpdateNewSpaceReferenceInExternalResourceTableEntry(Heap* heap, + Object** p) { MapWord first_word = HeapObject::cast(*p)->map_word(); - + if (!first_word.IsForwardingAddress()) { // Unreachable external string can be finalized. - heap->FinalizeExternalString(String::cast(*p)); + heap->FinalizeExternalString(HeapObject::cast(*p)); return NULL; } - + // String is still reachable. - return String::cast(first_word.ToForwardingAddress()); + return HeapObject::cast(first_word.ToForwardingAddress()); } - - + + -void Heap::UpdateNewSpaceReferencesInExternalStringTable( - ExternalStringTableUpdaterCallback updater_func) { - external_string_table_.Verify(); +void Heap::UpdateNewSpaceReferencesInExternalResourceTable( + ExternalResourceTableUpdaterCallback updater_func) { + external_resource_table_.Verify(); - + - if (external_string_table_.new_space_strings_.is_empty()) return; + if (external_resource_table_.new_space_objects_.is_empty()) return; - + - Object** start = &external_string_table_.new_space_strings_[0]; - Object** end = start + external_string_table_.new_space_strings_.length(); + Object** start = &external_resource_table_.new_space_objects_[0]; + Object** end = start + external_resource_table_.new_space_objects_.length(); Object** last = start; - + for (Object** p = start; p < end; ++p) { ASSERT(InFromSpace(*p)); - String* target = updater_func(this, p); + HeapObject* target = updater_func(this, p); - + if (target == NULL) continue; - + - ASSERT(target->IsExternalString()); + ASSERT(target->IsExternalString() || target->map()->has_external_resource()); - + if (InNewSpace(target)) { // String is still in new space. Update the table entry. @@ -1092,12 +1092,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( @@ -469,13 +469,13 @@ index 900f462..bf2940e 100644 + external_resource_table_.AddOldObject(target); } } - + ASSERT(last <= end); - external_string_table_.ShrinkNewStrings(static_cast(last - start)); + external_resource_table_.ShrinkNewObjects(static_cast(last - start)); } - - + + @@ -4468,7 +4468,7 @@ void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) { v->Synchronize("symbol_table"); if (mode != VISIT_ALL_IN_SCAVENGE) { @@ -486,18 +486,18 @@ index 900f462..bf2940e 100644 v->Synchronize("external_string_table"); } @@ -4970,7 +4970,7 @@ void Heap::TearDown() { - + isolate_->global_handles()->TearDown(); - + - external_string_table_.TearDown(); + external_resource_table_.TearDown(); - + new_space_.TearDown(); - + @@ -5835,31 +5835,31 @@ void TranscendentalCache::Clear() { } - - + + -void ExternalStringTable::CleanUp() { +void ExternalResourceTable::CleanUp() { int last = 0; @@ -530,8 +530,8 @@ index 900f462..bf2940e 100644 + old_space_objects_.Rewind(last); Verify(); } - - + + -void ExternalStringTable::TearDown() { - new_space_strings_.Free(); - old_space_strings_.Free(); @@ -539,33 +539,33 @@ index 900f462..bf2940e 100644 + new_space_objects_.Free(); + old_space_objects_.Free(); } - - + + diff --git a/src/heap.h b/src/heap.h index ae4e9e7..8cbf378 100644 --- a/src/heap.h +++ b/src/heap.h @@ -237,8 +237,8 @@ class Isolate; class WeakObjectRetainer; - - + + -typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, - Object** pointer); +typedef HeapObject* (*ExternalResourceTableUpdaterCallback)(Heap* heap, + Object** pointer); - + typedef bool (*DirtyRegionCallback)(Heap* heap, Address start, @@ -284,43 +284,45 @@ class PromotionQueue { }; - - + + -// External strings table is a place where all external strings are -// registered. We need to keep track of such strings to properly -// finalize them. -class ExternalStringTable { +// External resource table is a place where all external strings and -+// objects with an external resource are registered. We need to keep ++// objects with an external resource are registered. We need to keep +// track of such strings to properly finalize them. +class ExternalResourceTable { public: @@ -573,95 +573,95 @@ index ae4e9e7..8cbf378 100644 inline void AddString(String* string); + // Registers an external object. + inline void AddObject(HeapObject* object); - + inline void Iterate(ObjectVisitor* v); - + // Restores internal invariant and gets rid of collected strings. - // Must be called after each Iterate() that modified the strings. + // Must be called after each Iterate() that modified the objects. void CleanUp(); - + // Destroys all allocated memory. void TearDown(); - + private: - ExternalStringTable() { } + ExternalResourceTable() { } - + friend class Heap; - + inline void Verify(); - + - inline void AddOldString(String* string); + inline void AddOldObject(HeapObject* object); - + // Notifies the table that only a prefix of the new list is valid. - inline void ShrinkNewStrings(int position); + inline void ShrinkNewObjects(int position); - + // To speed up scavenge collections new space string are kept // separate from old space strings. - List new_space_strings_; - List old_space_strings_; + List new_space_objects_; + List old_space_objects_; - + Heap* heap_; - + - DISALLOW_COPY_AND_ASSIGN(ExternalStringTable); + DISALLOW_COPY_AND_ASSIGN(ExternalResourceTable); }; - - + + @@ -753,7 +755,7 @@ class Heap { - + // Finalizes an external string by deleting the associated external // data and clearing the resource pointer. - inline void FinalizeExternalString(String* string); + inline void FinalizeExternalString(HeapObject* string); - + // Allocates an uninitialized object. The memory is non-executable if the // hardware and OS allow. @@ -1191,8 +1193,8 @@ class Heap { survived_since_last_expansion_ += survived; } - + - void UpdateNewSpaceReferencesInExternalStringTable( - ExternalStringTableUpdaterCallback updater_func); + void UpdateNewSpaceReferencesInExternalResourceTable( + ExternalResourceTableUpdaterCallback updater_func); - + void ProcessWeakReferences(WeakObjectRetainer* retainer); - + @@ -1228,8 +1230,8 @@ class Heap { return &mark_compact_collector_; } - + - ExternalStringTable* external_string_table() { - return &external_string_table_; + ExternalResourceTable* external_resource_table() { + return &external_resource_table_; } - + inline Isolate* isolate(); @@ -1462,7 +1464,7 @@ class Heap { // Performs a minor collection in new generation. void Scavenge(); - + - static String* UpdateNewSpaceReferenceInExternalStringTableEntry( + static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry( Heap* heap, Object** pointer); - + @@ -1593,7 +1595,7 @@ class Heap { // configured through the API until it is setup. bool configured_; - + - ExternalStringTable external_string_table_; + ExternalResourceTable external_resource_table_; - + bool is_safe_to_read_maps_; - + diff --git a/src/liveobjectlist.cc b/src/liveobjectlist.cc index 5795a6b..8866e58 100644 --- a/src/liveobjectlist.cc @@ -685,26 +685,26 @@ index 5795a6b..8866e58 100644 } else { delete resource; diff --git a/src/mark-compact.cc b/src/mark-compact.cc -index 68a5062..1b1e361 100644 +index 68a5062..775f787 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -163,7 +163,7 @@ void MarkCompactCollector::Finish() { // objects (empty string, illegal builtin). heap()->isolate()->stub_cache()->Clear(); - + - heap()->external_string_table_.CleanUp(); + heap()->external_resource_table_.CleanUp(); - + // If we've just compacted old space there's no reason to check the // fragmentation limit. Just return. @@ -1019,8 +1019,9 @@ class SymbolTableCleaner : public ObjectVisitor { - + // Since no objects have yet been moved we can safely access the map of // the object. - if ((*p)->IsExternalString()) { - heap_->FinalizeExternalString(String::cast(*p)); + if ((*p)->IsExternalString() || -+ (*p)->IsHeapObject() && HeapObject::cast(*p)->map()->has_external_resource()) { ++ ((*p)->IsHeapObject() && HeapObject::cast(*p)->map()->has_external_resource())) { + heap_->FinalizeExternalString(HeapObject::cast(*p)); } // Set the entry to null_value (as deleted). @@ -717,13 +717,13 @@ index 68a5062..1b1e361 100644 - heap()->external_string_table_.CleanUp(); + heap()->external_resource_table_.Iterate(&v); + heap()->external_resource_table_.CleanUp(); - + // Process the weak references. MarkCompactWeakObjectRetainer mark_compact_object_retainer; @@ -1948,11 +1949,11 @@ static void UpdatePointerToNewGen(HeapObject** p) { } - - + + -static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, - Object** p) { +static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry(Heap* heap, @@ -733,17 +733,17 @@ index 68a5062..1b1e361 100644 - return String::cast(HeapObject::FromAddress(new_addr)); + return HeapObject::FromAddress(new_addr); } - - + + @@ -2083,8 +2084,8 @@ static void SweepNewSpace(Heap* heap, NewSpace* space) { updating_visitor.VisitPointer(heap->global_contexts_list_address()); - + // Update pointers from external string table. - heap->UpdateNewSpaceReferencesInExternalStringTable( - &UpdateNewSpaceReferenceInExternalStringTableEntry); + heap->UpdateNewSpaceReferencesInExternalResourceTable( + &UpdateNewSpaceReferenceInExternalResourceTableEntry); - + // All pointers were updated. Update auxiliary allocation info. heap->IncrementYoungSurvivorsCounter(survivors_size); diff --git a/src/objects-inl.h b/src/objects-inl.h @@ -757,15 +757,15 @@ index 6aaca2f..231b835 100644 - map()->inobject_properties(); + map()->inobject_properties() - map()->has_external_resource()?1:0; } - - + + int JSObject::GetInternalFieldOffset(int index) { ASSERT(index < GetInternalFieldCount() && index >= 0); - return GetHeaderSize() + (kPointerSize * index); + return GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); } - - + + @@ -1407,7 +1407,7 @@ Object* JSObject::GetInternalField(int index) { // Internal objects do follow immediately after the header, whereas in-object // properties are at the end of the object. Therefore there is no need @@ -773,8 +773,8 @@ index 6aaca2f..231b835 100644 - return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); + return READ_FIELD(this, GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0))); } - - + + @@ -1416,12 +1416,29 @@ void JSObject::SetInternalField(int index, Object* value) { // Internal objects do follow immediately after the header, whereas in-object // properties are at the end of the object. Therefore there is no need @@ -784,8 +784,8 @@ index 6aaca2f..231b835 100644 WRITE_FIELD(this, offset, value); WRITE_BARRIER(this, offset); } - - + + +void JSObject::SetExternalResourceObject(Object *value) { + ASSERT(map()->has_external_resource()); + int offset = GetHeaderSize(); @@ -794,7 +794,7 @@ index 6aaca2f..231b835 100644 +} + + -+Object *JSObject::GetExternalResourceObject() { ++Object *JSObject::GetExternalResourceObject() { + if (map()->has_external_resource()) { + return READ_FIELD(this, GetHeaderSize()); + } else { @@ -808,8 +808,8 @@ index 6aaca2f..231b835 100644 // properties stored in the properties array. @@ -2521,6 +2538,20 @@ bool Map::is_shared() { } - - + + +void Map::set_has_external_resource(bool value) { + if (value) { + set_bit_field3(bit_field3() | (1 << kHasExternalResource)); @@ -822,7 +822,7 @@ index 6aaca2f..231b835 100644 +{ + return ((1 << kHasExternalResource) & bit_field3()) != 0; +} -+ ++ + void Map::set_named_interceptor_is_fallback(bool value) { @@ -831,9 +831,9 @@ index 6aaca2f..231b835 100644 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, kInternalFieldCountOffset) -+ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, ++ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, + kHasExternalResourceOffset) - + ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) ACCESSORS(SignatureInfo, args, Object, kArgsOffset) diff --git a/src/objects.h b/src/objects.h @@ -843,7 +843,7 @@ index a209cd0..1bdb5c7 100644 @@ -1636,6 +1636,9 @@ class JSObject: public HeapObject { inline Object* GetInternalField(int index); inline void SetInternalField(int index, Object* value); - + + inline void SetExternalResourceObject(Object *); + inline Object *GetExternalResourceObject(); + @@ -853,22 +853,22 @@ index a209cd0..1bdb5c7 100644 @@ -3715,6 +3718,12 @@ class Map: public HeapObject { inline void set_is_access_check_needed(bool access_check_needed); inline bool is_access_check_needed(); - + + + // Tells whether the instance has the space for an external resource + // object + inline void set_has_external_resource(bool value); + inline bool has_external_resource(); + - + // Whether the named interceptor is a fallback interceptor or not inline void set_named_interceptor_is_fallback(bool value); @@ -3912,6 +3921,7 @@ class Map: public HeapObject { - + // Bit positions for bit field 3 static const int kNamedInterceptorIsFallback = 0; + static const int kHasExternalResource = 1; - + // Layout of the default cache. It holds alternating name and code objects. static const int kCodeCacheEntrySize = 2; @@ -6426,6 +6436,7 @@ class ObjectTemplateInfo: public TemplateInfo { @@ -876,9 +876,9 @@ index a209cd0..1bdb5c7 100644 DECL_ACCESSORS(constructor, Object) DECL_ACCESSORS(internal_field_count, Object) + DECL_ACCESSORS(has_external_resource, Object) - + static inline ObjectTemplateInfo* cast(Object* obj); - + @@ -6442,7 +6453,8 @@ class ObjectTemplateInfo: public TemplateInfo { static const int kConstructorOffset = TemplateInfo::kHeaderSize; static const int kInternalFieldCountOffset = @@ -887,8 +887,8 @@ index a209cd0..1bdb5c7 100644 + static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; + static const int kSize = kHasExternalResourceOffset + kPointerSize; }; - - --- -1.7.6 + + +-- +1.7.4.4 diff --git a/src/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0005-Introduce-a-QML-compilation-mode.patch index 3c1cab24970..4904969a83b 100644 --- a/src/v8/0005-Introduce-a-QML-compilation-mode.patch +++ b/src/v8/0005-Introduce-a-QML-compilation-mode.patch @@ -1,7 +1,7 @@ -From fd7d475e298e5b63cd6383c78cc900635c82aa38 Mon Sep 17 00:00:00 2001 +From 60c1a26bf89d3b06bcdd8408fcee89a018120f32 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 23 May 2011 18:26:19 +1000 -Subject: [PATCH 05/16] Introduce a QML compilation mode +Subject: [PATCH 05/15] Introduce a QML compilation mode In QML mode, there is a second global object - known as the QML global object. During property resolution, if a property is not @@ -15,8 +15,8 @@ closures etc. created during the run will retain a reference to this object, so different objects can be passed in different script runs. --- - include/v8.h | 18 ++++++++-- - src/api.cc | 52 ++++++++++++++++++++++++----- + include/v8.h | 18 +++++++-- + src/api.cc | 52 ++++++++++++++++++++++----- src/arm/code-stubs-arm.cc | 4 ++ src/arm/full-codegen-arm.cc | 26 ++++++++------ src/arm/lithium-arm.cc | 2 +- @@ -27,10 +27,10 @@ runs. src/ast.h | 1 + src/code-stubs.h | 2 +- src/compiler.cc | 15 +++++++- - src/compiler.h | 22 ++++++++++-- - src/contexts.cc | 23 +++++++++++++ + src/compiler.h | 22 +++++++++-- + src/contexts.cc | 35 ++++++++++++++++++ src/contexts.h | 4 ++ - src/execution.cc | 28 +++++++++++++-- + src/execution.cc | 28 ++++++++++++-- src/execution.h | 6 +++ src/full-codegen.cc | 3 +- src/full-codegen.h | 1 + @@ -43,14 +43,14 @@ runs. src/ia32/lithium-ia32.cc | 2 +- src/ia32/lithium-ia32.h | 6 +++- src/ia32/macro-assembler-ia32.h | 5 +++ - src/objects-inl.h | 12 +++++++ + src/objects-inl.h | 12 ++++++ src/objects.h | 5 +++ - src/parser.cc | 27 +++++++++++++-- + src/parser.cc | 27 ++++++++++++-- src/parser.h | 4 ++- src/prettyprinter.cc | 3 ++ - src/runtime.cc | 68 ++++++++++++++++++++++++------------- + src/runtime.cc | 72 ++++++++++++++++++++++++------------- src/runtime.h | 8 ++-- - src/scopes.cc | 10 +++++ + src/scopes.cc | 59 +++++++++++++++++++++++++++++++ src/scopes.h | 7 ++++ src/variables.cc | 3 +- src/variables.h | 5 +++ @@ -60,10 +60,10 @@ runs. src/x64/lithium-x64.cc | 2 +- src/x64/lithium-x64.h | 6 +++ src/x64/macro-assembler-x64.h | 5 +++ - 45 files changed, 391 insertions(+), 108 deletions(-) + 45 files changed, 455 insertions(+), 109 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 7f06ae7..a858eae 100644 +index 205e856..d78ab1f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -577,6 +577,10 @@ class ScriptOrigin { @@ -74,7 +74,7 @@ index 7f06ae7..a858eae 100644 + Default = 0x00, + QmlMode = 0x01 + }; - + /** * Compiles the specified script (context-independent). @@ -596,7 +600,8 @@ class V8EXPORT Script { @@ -84,7 +84,7 @@ index 7f06ae7..a858eae 100644 - Handle script_data = Handle()); + Handle script_data = Handle(), + CompileFlags = Default); - + /** * Compiles the specified script using the specified file name @@ -609,7 +614,8 @@ class V8EXPORT Script { @@ -94,7 +94,7 @@ index 7f06ae7..a858eae 100644 - Handle file_name); + Handle file_name, + CompileFlags = Default); - + /** * Compiles the specified script (bound to current context). @@ -630,7 +636,8 @@ class V8EXPORT Script { @@ -104,7 +104,7 @@ index 7f06ae7..a858eae 100644 - Handle script_data = Handle()); + Handle script_data = Handle(), + CompileFlags = Default); - + /** * Compiles the specified script using the specified file name @@ -647,7 +654,8 @@ class V8EXPORT Script { @@ -114,7 +114,7 @@ index 7f06ae7..a858eae 100644 - Handle script_data = Handle()); + Handle script_data = Handle(), + CompileFlags = Default); - + /** * Runs the script returning the resulting value. If the script is @@ -657,6 +665,7 @@ class V8EXPORT Script { @@ -122,15 +122,15 @@ index 7f06ae7..a858eae 100644 */ Local Run(); + Local Run(Handle qml); - + /** * Returns the script id value. -@@ -3326,6 +3335,7 @@ class V8EXPORT Context { +@@ -3327,6 +3336,7 @@ class V8EXPORT Context { * JavaScript frames an empty handle is returned. */ static Local GetCalling(); + static Local GetCallingQmlGlobal(); - + /** * Sets the security token for the context. To access an object in diff --git a/src/api.cc b/src/api.cc @@ -158,18 +158,18 @@ index 1a6fbbb..39767f4 100644 EXCEPTION_BAILOUT_CHECK(isolate, Local