diff --git a/CMakeLists.txt b/CMakeLists.txt index abca779c3ac..ffceb6b057c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,6 +310,28 @@ endif(WITHOUT_FEATURES_SH) enable_language(ASM) +################# Write-barrier check/analyze ################## +if (WB_CHECK_SH OR WB_ANALYZE_SH) + add_definitions( + -Xclang -load + -Xclang ${CMAKE_CURRENT_SOURCE_DIR}/tools/RecyclerChecker/Build/libclangRecyclerChecker.so + ) +endif() +if (WB_CHECK_SH) + unset(WB_CHECK_SH CACHE) # don't cache + add_definitions( + -Xclang -plugin + -Xclang check-recycler + ) +endif() +if (WB_ANALYZE_SH) + unset(WB_ANALYZE_SH CACHE) # don't cache + add_definitions( + -Xclang -analyze + -Xclang -analyzer-checker=chakra.RecyclerChecker + ) +endif() + include_directories( . lib/Common diff --git a/build.sh b/build.sh index 700c03be894..1ee2880a528 100755 --- a/build.sh +++ b/build.sh @@ -49,6 +49,10 @@ PRINT_USAGE() { echo " --without=FEATURE,FEATURE,..." echo " Disable FEATUREs from JSRT experimental" echo " features." + echo " --wb-check CPPFILE" + echo " Write-barrier check given CPPFILE (git path)" + echo " --wb-analyze CPPFILE" + echo " Write-barrier analyze given CPPFILE (git path)" echo "" echo "example:" echo " ./build.sh --cxx=/path/to/clang++ --cc=/path/to/clang -j" @@ -75,6 +79,8 @@ ARCH="-DCC_TARGETS_AMD64_SH=1" OS_LINUX=0 OS_APT_GET=0 OS_UNIX=0 +WB_CHECK= +WB_ANALYZE= if [ -f "/proc/version" ]; then OS_LINUX=1 @@ -234,6 +240,24 @@ while [[ $# -gt 0 ]]; do done ;; + --wb-check) + if [[ "$2" =~ ^[^-] ]]; then + WB_CHECK="$2" + shift + else + PRINT_USAGE && exit 1 + fi + ;; + + --wb-analyze) + if [[ "$2" =~ ^[^-] ]]; then + WB_ANALYZE="$2" + shift + else + PRINT_USAGE && exit 1 + fi + ;; + *) echo "Unknown option $1" PRINT_USAGE @@ -306,6 +330,43 @@ if [[ ${#_CXX} > 0 ]]; then CC_PREFIX="-DCMAKE_CXX_COMPILER=$_CXX -DCMAKE_C_COMPILER=$_CC" fi +################# Write-barrier check/analyze run ################# +WB_FLAG= +WB_TARGET= +if [[ $WB_CHECK || $WB_ANALYZE ]]; then + if [[ $MAKE != 'ninja' ]]; then + echo "--wb-check/wb-analyze only works with --ninja" && exit 1 + fi + if [[ $WB_CHECK && $WB_ANALYZE ]]; then + echo "Please run only one of --wb-check or --wb-analyze" && exit 1 + fi + if [[ $WB_CHECK ]]; then + WB_FLAG="-DWB_CHECK_SH=1" + WB_FILE=$WB_CHECK + fi + if [[ $WB_ANALYZE ]]; then + WB_FLAG="-DWB_ANALYZE_SH=1" + WB_FILE=$WB_ANALYZE + fi + + if [[ -f $CHAKRACORE_DIR/$WB_FILE ]]; then + touch $CHAKRACORE_DIR/$WB_FILE + else + echo "$CHAKRACORE_DIR/$WB_FILE not found. Please use full git path for $WB_FILE." && exit 1 + fi + + WB_FILE_DIR=`dirname $WB_FILE` + WB_FILE_BASE=`basename $WB_FILE` + + WB_FILE_CMAKELISTS="$CHAKRACORE_DIR/$WB_FILE_DIR/CMakeLists.txt" + if [[ -f $WB_FILE_CMAKELISTS ]]; then + SUBDIR=$(grep -i add_library $WB_FILE_CMAKELISTS | sed -r "s/.*\((\S+) .*/\1/") + else + echo "$WB_FILE_CMAKELISTS not found." && exit 1 + fi + WB_TARGET="$WB_FILE_DIR/CMakeFiles/$SUBDIR.dir/$WB_FILE_BASE.o" +fi + build_directory="$CHAKRACORE_DIR/BuildLinux/${BUILD_TYPE:0}" if [ ! -d "$build_directory" ]; then SAFE_RUN `mkdir -p $build_directory` @@ -322,12 +383,14 @@ fi echo Generating $BUILD_TYPE makefiles cmake $CMAKE_GEN $CC_PREFIX $ICU_PATH $STATIC_LIBRARY $ARCH \ - -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SANITIZE $NO_JIT $WITHOUT_FEATURES ../.. + -DCMAKE_BUILD_TYPE=$BUILD_TYPE $SANITIZE $NO_JIT $WITHOUT_FEATURES \ + $WB_FLAG \ + ../.. _RET=$? if [[ $? == 0 ]]; then if [[ $MAKE != 0 ]]; then - $MAKE $MULTICORE_BUILD 2>&1 | tee build.log + $MAKE $MULTICORE_BUILD $WB_TARGET 2>&1 | tee build.log _RET=${PIPESTATUS[0]} else echo "Visit given folder above for xcode project file ----^" diff --git a/jenkins/check_copyright.sh b/jenkins/check_copyright.sh index c457db0f5d0..3e4d9c14b07 100755 --- a/jenkins/check_copyright.sh +++ b/jenkins/check_copyright.sh @@ -32,6 +32,7 @@ git diff --name-only `git merge-base origin/master HEAD` HEAD | grep -v -E '\.nuspec$' | grep -v -E '\.def$' | grep -v -E '\.inc$' | + grep -v -E '\.cmake$' | grep -v -E 'test/benchmarks/.*\.js$' | grep -v -E 'bin/External/.*$' | grep -v -E 'bin/NativeTests/Scripts/splay.js$' | @@ -39,6 +40,8 @@ git diff --name-only `git merge-base origin/master HEAD` HEAD | grep -v -E 'libChakraCoreLib.version|ch.version' | xargs -I % sh -c "echo 'Check Copyright > Checking %'; python jenkins/check_copyright.py % > $ERRFILETEMP || cat $ERRFILETEMP >> $ERRFILE" +rm -f $ERRFILETEMP + if [ -e $ERRFILE ]; then # if error file exists then there were errors >&2 echo "--------------" # leading >&2 means echo to stderr >&2 echo "--- ERRORS ---" diff --git a/lib/Backend/LowerMDShared.cpp b/lib/Backend/LowerMDShared.cpp index 35610ff5681..938ae3b6d63 100644 --- a/lib/Backend/LowerMDShared.cpp +++ b/lib/Backend/LowerMDShared.cpp @@ -1675,7 +1675,8 @@ LowererMD::Legalize(IR::Instr *const instr, bool fPostRegAlloc) case Js::OpCode::LEA: Assert(instr->GetDst()->IsRegOpnd()); - Assert(instr->GetSrc1()->IsIndirOpnd() || instr->GetSrc1()->IsSymOpnd()); + Assert(instr->GetSrc1()->IsIndirOpnd() || instr->GetSrc1()->IsSymOpnd() + || instr->GetSrc1()->IsMemRefOpnd()); // We may convert IndirOpnd to MemRefOpnd Assert(!instr->GetSrc2()); break; case Js::OpCode::PSRLDQ: @@ -5031,7 +5032,7 @@ LowererMD::GenerateUntagVar(IR::RegOpnd * src, IR::LabelInstr * labelFail, IR::I if (generateTagCheck) { Assert(!opnd->IsTaggedInt()); - this->GenerateSmIntTest(opnd, insertBeforeInstr, labelFail); + this->GenerateSmIntTest(opnd, assignInstr, labelFail); } // Moving into r2 clears the tag bits on AMD64. diff --git a/lib/Common/CommonDefines.h b/lib/Common/CommonDefines.h index 79f45c07a04..90d36a8081d 100644 --- a/lib/Common/CommonDefines.h +++ b/lib/Common/CommonDefines.h @@ -154,8 +154,6 @@ #ifdef RECYCLER_WRITE_BARRIER #if defined(__clang__) #define GLOBAL_FORCE_USE_WRITE_BARRIER 1 -#else -#define GLOBAL_FORCE_USE_WRITE_BARRIER 1 // force turn on write barrier in windows #endif #endif diff --git a/lib/Common/Memory/Recycler.h b/lib/Common/Memory/Recycler.h index d4ae554c596..ba9f6e816b2 100644 --- a/lib/Common/Memory/Recycler.h +++ b/lib/Common/Memory/Recycler.h @@ -129,7 +129,7 @@ struct InfoBitsWrapper{}; #define RecyclerNewFinalized(recycler,T,...) static_cast(static_cast(AllocatorNewBase(Recycler, recycler, AllocFinalizedInlined, T, __VA_ARGS__))) #define RecyclerNewFinalizedPlus(recycler, size, T,...) static_cast(static_cast(AllocatorNewPlusBase(Recycler, recycler, AllocFinalized, size, T, __VA_ARGS__))) #define RecyclerNewTracked(recycler,T,...) static_cast(static_cast(AllocatorNewBase(Recycler, recycler, AllocTrackedInlined, T, __VA_ARGS__))) -#define RecyclerNewEnumClass(recycler, enumClass, T, ...) new (TRACK_ALLOC_INFO(static_cast(recycler), T, Recycler, 0, (size_t)-1), enumClass) T(__VA_ARGS__) +#define RecyclerNewEnumClass(recycler, enumClass, T, ...) new (TRACK_ALLOC_INFO(static_cast(recycler), T, Recycler, 0, (size_t)-1), InfoBitsWrapper()) T(__VA_ARGS__) #define RecyclerNewWithInfoBits(recycler, infoBits, T, ...) new (TRACK_ALLOC_INFO(static_cast(recycler), T, Recycler, 0, (size_t)-1), InfoBitsWrapper()) T(__VA_ARGS__) #define RecyclerNewFinalizedClientTracked(recycler,T,...) static_cast(static_cast(AllocatorNewBase(Recycler, recycler, AllocFinalizedClientTrackedInlined, T, __VA_ARGS__))) #endif @@ -1351,7 +1351,7 @@ class Recycler char * AllocEnumClass(DECLSPEC_GUARD_OVERFLOW size_t size) { Assert((enumClass & EnumClassMask) != 0); - Assert((enumClass & ~EnumClassMask & ~WithBarrierBit) == 0); + //Assert((enumClass & ~EnumClassMask & ~WithBarrierBit) == 0); return AllocWithAttributes<(ObjectInfoBits)(enumClass), /* nothrow = */ false>(size); } diff --git a/lib/Runtime/Base/AuxPtrs.h b/lib/Runtime/Base/AuxPtrs.h index 117123e74e7..855aee4ad0d 100644 --- a/lib/Runtime/Base/AuxPtrs.h +++ b/lib/Runtime/Base/AuxPtrs.h @@ -25,16 +25,19 @@ namespace Js template struct AuxPtrsFix { - static const uint8 MaxCount = _MaxCount; - Field(uint8) count; // always saving maxCount - Field(FieldsEnum) type[MaxCount]; // save instantiated pointer enum - Pointer(void) ptr[MaxCount]; // save instantiated pointer address + static const uint8 MaxCount; + Field(uint8) count; // always saving maxCount + Field(FieldsEnum) type[_MaxCount]; // save instantiated pointer enum + Pointer(void) ptr[_MaxCount]; // save instantiated pointer address AuxPtrsFix(); AuxPtrsFix(AuxPtrsFix* ptr16); // called when promoting from AuxPtrs16 to AuxPtrs32 void* Get(FieldsEnum e); bool Set(FieldsEnum e, void* p); }; + template + const uint8 AuxPtrsFix::MaxCount = _MaxCount; + // Use flexible size structure to save pointers. when pointer count exceeds AuxPtrsFix::MaxCount, // it will promote to this structure to save the pointers // Layout: diff --git a/lib/Runtime/Language/ModuleNamespace.cpp b/lib/Runtime/Language/ModuleNamespace.cpp index f5c7928c2f3..818d960eee5 100644 --- a/lib/Runtime/Language/ModuleNamespace.cpp +++ b/lib/Runtime/Language/ModuleNamespace.cpp @@ -16,7 +16,7 @@ namespace Js Js::FunctionInfo ModuleNamespace::EntryInfo::SymbolIterator(ModuleNamespace::EntrySymbolIterator); ModuleNamespace::ModuleNamespace(ModuleRecordBase* moduleRecord, DynamicType* type) : - moduleRecord(moduleRecord), DynamicObject(type), unambiguousNonLocalExports(nullptr), + moduleRecord(moduleRecord), DynamicObject(type), unambiguousNonLocalExports(nullptr), sortedExportedNames(nullptr), nsSlots(nullptr) { @@ -56,7 +56,7 @@ namespace Js DynamicType* type = library->CreateFunctionWithLengthType(&EntryInfo::SymbolIterator); RuntimeFunction* iteratorFunction = RecyclerNewEnumClass(scriptContext->GetRecycler(), - library->EnumFunctionClass, RuntimeFunction, + JavascriptLibrary::EnumFunctionClass, RuntimeFunction, type, &EntryInfo::SymbolIterator); DynamicObject::SetPropertyWithAttributes(PropertyIds::_symbolIterator, iteratorFunction, PropertyBuiltInMethodDefaults, nullptr); @@ -89,7 +89,7 @@ namespace Js // update the local slot to use the storage for local exports. SetNSSlotsForModuleNS(sourceTextModuleRecord->GetLocalExportSlots()); - // For items that are not in the local export list, we need to resolve them to get it + // For items that are not in the local export list, we need to resolve them to get it ExportedNames* exportedNames = sourceTextModuleRecord->GetExportedNames(nullptr); ModuleNameRecord* moduleNameRecord = nullptr; #if DBG diff --git a/lib/Runtime/Library/JavascriptLibrary.cpp b/lib/Runtime/Library/JavascriptLibrary.cpp index 0fbc5d2c752..1efce42f9d7 100644 --- a/lib/Runtime/Library/JavascriptLibrary.cpp +++ b/lib/Runtime/Library/JavascriptLibrary.cpp @@ -5024,7 +5024,7 @@ namespace Js Js::RecyclableObject* JavascriptLibrary::CreateRevokeFunction_TTD(RecyclableObject* proxy) { - RuntimeFunction* revoker = RecyclerNewEnumClass(this->scriptContext->GetRecycler(), this->EnumFunctionClass, RuntimeFunction, this->CreateFunctionWithLengthType(&JavascriptProxy::EntryInfo::Revoke), &JavascriptProxy::EntryInfo::Revoke); + RuntimeFunction* revoker = RecyclerNewEnumClass(this->scriptContext->GetRecycler(), JavascriptLibrary::EnumFunctionClass, RuntimeFunction, this->CreateFunctionWithLengthType(&JavascriptProxy::EntryInfo::Revoke), &JavascriptProxy::EntryInfo::Revoke); revoker->SetPropertyWithAttributes(Js::PropertyIds::length, Js::TaggedInt::ToVarUnchecked(0), PropertyNone, NULL); revoker->SetInternalProperty(Js::InternalPropertyIds::RevocableProxy, proxy, PropertyOperationFlags::PropertyOperation_Force, nullptr); diff --git a/lib/Runtime/Library/JavascriptProxy.cpp b/lib/Runtime/Library/JavascriptProxy.cpp index 1d711814f96..93921a15b6b 100644 --- a/lib/Runtime/Library/JavascriptProxy.cpp +++ b/lib/Runtime/Library/JavascriptProxy.cpp @@ -126,7 +126,7 @@ namespace Js JavascriptLibrary* library = scriptContext->GetLibrary(); DynamicType* type = library->CreateFunctionWithLengthType(&EntryInfo::Revoke); RuntimeFunction* revoker = RecyclerNewEnumClass(scriptContext->GetRecycler(), - library->EnumFunctionClass, RuntimeFunction, + JavascriptLibrary::EnumFunctionClass, RuntimeFunction, type, &EntryInfo::Revoke); revoker->SetPropertyWithAttributes(Js::PropertyIds::length, Js::TaggedInt::ToVarUnchecked(0), PropertyNone, NULL); @@ -906,8 +906,8 @@ namespace Js if (!threadContext->RecordImplicitException()) return FALSE; JavascriptError::ThrowTypeError(GetScriptContext(), JSERR_ErrorOnRevokedProxy, _u("ownKeys")); - } - + } + Var propertyName = nullptr; PropertyId propertyId; int index = 0; @@ -915,7 +915,7 @@ namespace Js JavascriptArray* arrResult = requestContext->GetLibrary()->CreateArray(); // 13.7.5.15 EnumerateObjectProperties(O) (https://tc39.github.io/ecma262/#sec-enumerate-object-properties) - // for (let key of Reflect.ownKeys(obj)) { + // for (let key of Reflect.ownKeys(obj)) { Var trapResult = JavascriptOperators::GetOwnPropertyNames(this, requestContext); if (JavascriptArray::Is(trapResult)) { @@ -941,7 +941,7 @@ namespace Js dict.Add(str->GetSz(), prop); // if (desc.enumerable) yield key; if (desc.IsEnumerable()) - { + { ret = arrResult->SetItem(index++, CrossSite::MarshalVar(requestContext, prop), PropertyOperation_None); Assert(ret); } @@ -1230,7 +1230,7 @@ namespace Js //7. ReturnIfAbrupt(keys). JavascriptArray* resultArray = JavascriptOperators::GetOwnPropertyKeys(obj, scriptContext); - const PropertyRecord* propertyRecord; + const PropertyRecord* propertyRecord; if (integrityLevel == IntegrityLevel::IntegrityLevel_sealed) { //8. If level is "sealed", then diff --git a/lib/Runtime/Library/TypedArray.cpp b/lib/Runtime/Library/TypedArray.cpp index cef8cf0df42..654ffe41eb0 100644 --- a/lib/Runtime/Library/TypedArray.cpp +++ b/lib/Runtime/Library/TypedArray.cpp @@ -1025,71 +1025,6 @@ namespace Js } - template - TypedArray::TypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 mappedLength, DynamicType* type) : - TypedArrayBase(arrayBuffer, byteOffset, mappedLength, sizeof(TypeName), type) - { - AssertMsg(arrayBuffer->GetByteLength() >= byteOffset, "invalid offset"); - AssertMsg(mappedLength*sizeof(TypeName)+byteOffset <= arrayBuffer->GetByteLength(), "invalid length"); - buffer = arrayBuffer->GetBuffer() + byteOffset; - if (arrayBuffer->IsValidVirtualBufferLength(arrayBuffer->GetByteLength()) && - (byteOffset == 0) && - (mappedLength == (arrayBuffer->GetByteLength() / sizeof(TypeName))) - ) - { - // update the vtable - switch (type->GetTypeId()) - { - case TypeIds_Int8Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Uint8Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Uint8ClampedArray: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Int16Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Uint16Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Int32Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Uint32Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Float32Array: - VirtualTableInfo::SetVirtualTable(this); - break; - case TypeIds_Float64Array: - VirtualTableInfo::SetVirtualTable(this); - break; - default: - break; - } - } - } - - template - inline Var TypedArray::Create(ArrayBufferBase* arrayBuffer, uint32 byteOffSet, uint32 mappedLength, JavascriptLibrary* javascriptLibrary) - { - uint32 totalLength, mappedByteLength; - - if (UInt32Math::Mul(mappedLength, sizeof(TypeName), &mappedByteLength) || - UInt32Math::Add(byteOffSet, mappedByteLength, &totalLength) || - (totalLength > arrayBuffer->GetByteLength())) - { - JavascriptError::ThrowRangeError(arrayBuffer->GetScriptContext(), JSERR_InvalidTypedArrayLength); - } - - DynamicType *type = javascriptLibrary->GetTypedArrayType(0); - return RecyclerNew(javascriptLibrary->GetRecycler(), TypedArray, arrayBuffer, byteOffSet, mappedLength, type); - - } - Var TypedArrayBase::EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); @@ -2573,7 +2508,7 @@ namespace Js return Js::JavascriptNumber::ToVarNoCheck(currentRes, scriptContext); } - // static + // static TypedArrayBase * TypedArrayBase::ValidateTypedArray(Arguments &args, ScriptContext *scriptContext, LPCWSTR apiName) { if (args.Info.Count == 0) @@ -3365,18 +3300,4 @@ namespace Js #endif return object; } - - // Instantiate the constructor function directly - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); - template TypedArray::TypedArray(ArrayBufferBase*, uint32, uint32, DynamicType*); } diff --git a/lib/Runtime/Library/TypedArray.h b/lib/Runtime/Library/TypedArray.h index 8d5fb043b36..fac0b0f5079 100644 --- a/lib/Runtime/Library/TypedArray.h +++ b/lib/Runtime/Library/TypedArray.h @@ -499,6 +499,71 @@ namespace Js } }; + + template + TypedArray::TypedArray(ArrayBufferBase* arrayBuffer, uint32 byteOffset, uint32 mappedLength, DynamicType* type) : + TypedArrayBase(arrayBuffer, byteOffset, mappedLength, sizeof(TypeName), type) + { + AssertMsg(arrayBuffer->GetByteLength() >= byteOffset, "invalid offset"); + AssertMsg(mappedLength*sizeof(TypeName)+byteOffset <= arrayBuffer->GetByteLength(), "invalid length"); + buffer = arrayBuffer->GetBuffer() + byteOffset; + if (arrayBuffer->IsValidVirtualBufferLength(arrayBuffer->GetByteLength()) && + (byteOffset == 0) && + (mappedLength == (arrayBuffer->GetByteLength() / sizeof(TypeName))) + ) + { + // update the vtable + switch (type->GetTypeId()) + { + case TypeIds_Int8Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Uint8Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Uint8ClampedArray: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Int16Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Uint16Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Int32Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Uint32Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Float32Array: + VirtualTableInfo::SetVirtualTable(this); + break; + case TypeIds_Float64Array: + VirtualTableInfo::SetVirtualTable(this); + break; + default: + break; + } + } + } + + template + Var TypedArray::Create(ArrayBufferBase* arrayBuffer, uint32 byteOffSet, uint32 mappedLength, JavascriptLibrary* javascriptLibrary) + { + uint32 totalLength, mappedByteLength; + + if (UInt32Math::Mul(mappedLength, sizeof(TypeName), &mappedByteLength) || + UInt32Math::Add(byteOffSet, mappedByteLength, &totalLength) || + (totalLength > arrayBuffer->GetByteLength())) + { + JavascriptError::ThrowRangeError(arrayBuffer->GetScriptContext(), JSERR_InvalidTypedArrayLength); + } + + DynamicType *type = javascriptLibrary->GetTypedArrayType(0); + return RecyclerNew(javascriptLibrary->GetRecycler(), TypedArray, arrayBuffer, byteOffSet, mappedLength, type); + } + #if defined(__clang__) // hack for clang message: "...add an explicit instantiation declaration to .." #define __EXPLICIT_INSTANTINATE_TA(x) x;\ diff --git a/tools/RecyclerChecker/RecyclerAnalyzer.cpp b/tools/RecyclerChecker/RecyclerAnalyzer.cpp index f627c0225a7..d596a7b26b9 100644 --- a/tools/RecyclerChecker/RecyclerAnalyzer.cpp +++ b/tools/RecyclerChecker/RecyclerAnalyzer.cpp @@ -1,10 +1,8 @@ -//===-- PHPZPPChecker.cpp -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + //===----------------------------------------------------------------------===// // // Defines a checker for proper use of Recycler Write Barrier functionality @@ -26,7 +24,7 @@ using namespace ento; class RecyclerChecker : public Checker > { std::unique_ptr InvalidAllocatorBugType; - + public: RecyclerChecker(); @@ -66,7 +64,7 @@ static bool isCastToRecycler(const CXXStaticCastExpr* castNode) { return false; } - + QualType targetType = castNode->getTypeAsWritten(); if (const IdentifierInfo* info = targetType.getBaseTypeIdentifier()) { @@ -99,7 +97,7 @@ void RecyclerChecker::checkPostStmt(const CXXNewExpr* newExpr, CheckerContext& c (castNode = const_cast(dyn_cast(firstArgNode)))) { //printf("Expr is %s\n", firstArgNode->getStmtClassName()); - + if (isCastToRecycler(castNode)) { //printf("Recycler allocation found\n"); @@ -116,7 +114,7 @@ void RecyclerChecker::checkPostStmt(const CXXNewExpr* newExpr, CheckerContext& c { auto declNameInfo = declRef->getNameInfo(); printf("AllocFunc: %s\n", declNameInfo.getName().getAsString().c_str()); - + if (const IdentifierInfo* info = newExpr->getAllocatedType().getBaseTypeIdentifier()) { printf("Type: %s\n", info->getName().str().c_str()); @@ -148,7 +146,7 @@ void RecyclerChecker::checkPostStmt(const CXXNewExpr* newExpr, CheckerContext& c } */ } - } + } } static void initRecyclerChecker(CheckerManager &mgr) { diff --git a/tools/RecyclerChecker/RecyclerChecker.cpp b/tools/RecyclerChecker/RecyclerChecker.cpp index 01155cd580a..246396ebbd3 100644 --- a/tools/RecyclerChecker/RecyclerChecker.cpp +++ b/tools/RecyclerChecker/RecyclerChecker.cpp @@ -1,16 +1,7 @@ -//===- RecyclerChecker.cpp ---------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Example clang plugin which simply prints the names of all the top-level decls -// in the input file. -// -//===----------------------------------------------------------------------===// +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/AST/AST.h" @@ -22,7 +13,7 @@ using namespace clang; using namespace std; - + namespace { @@ -39,7 +30,7 @@ class CheckAllocationsInFunctionVisitor : } bool VisitCXXNewExpr(CXXNewExpr* newExpression); - + private: MainVisitor* _mainVisitor; FunctionDecl* _functionDecl; @@ -52,7 +43,7 @@ class MainVisitor: bool VisitCXXRecordDecl(CXXRecordDecl* recordDecl) { std::string typeName = recordDecl->getQualifiedNameAsString(); - + if (!_barrierTypeDefined) { if (typeName == "Memory::NoWriteBarrierField") @@ -64,18 +55,18 @@ class MainVisitor: return true; } } - + if (recordDecl->hasDefinition()) { bool hasUnbarrieredPointer = false; const FieldDecl* unbarrieredPointerField = nullptr; bool hasBarrieredField = false; - + for (auto field : recordDecl->fields()) { const QualType qualType = field->getType(); const Type* type = qualType.getTypePtr(); - + if (type->isPointerType()) { hasUnbarrieredPointer = true; @@ -114,7 +105,7 @@ class MainVisitor: { _pointerClasses.insert(typeName); } - + if (hasBarrieredField) { llvm::outs()<<"Type with barrier found: \""<hasBody()) @@ -141,7 +132,7 @@ class MainVisitor: visitor.TraverseDecl(functionDecl); } - return true; + return true; } void RecordWriteBarrierAllocation(const string& allocationType) @@ -153,7 +144,7 @@ class MainVisitor: { _allocatorTypeMap[allocationFunction].insert(type); } - + MainVisitor(): _barrierTypeDefined(false) { @@ -161,7 +152,7 @@ class MainVisitor: #define Dump(coll) \ dump(_##coll, #coll) - + void Inspect() { Dump(pointerClasses); @@ -172,10 +163,10 @@ class MainVisitor: { dump(item.second, item.first.c_str()); } - + Dump(barrierAllocations); } - + private: void dump(const set& set, const char* name) { @@ -187,8 +178,8 @@ class MainVisitor: llvm::outs()<<" "< > _allocatorTypeMap; set _pointerClasses; @@ -203,7 +194,7 @@ static bool isCastToRecycler(const CXXStaticCastExpr* castNode) { return false; } - + QualType targetType = castNode->getTypeAsWritten(); if (const IdentifierInfo* info = targetType.getBaseTypeIdentifier()) { @@ -246,13 +237,13 @@ bool CheckAllocationsInFunctionVisitor::VisitCXXNewExpr(CXXNewExpr* newExpr) auto declNameInfo = declRef->getNameInfo(); auto allocationFunctionStr = declNameInfo.getName().getAsString(); _mainVisitor->RecordRecyclerAllocation(allocationFunctionStr, allocatedTypeStr); - + if (allocationFunctionStr.find("WithBarrier") != string::npos) { llvm::outs()<<"In \""<<_functionDecl->getQualifiedNameAsString()<<"\"\n"; llvm::outs()<<" Allocating \""<RecordWriteBarrierAllocation(allocatedTypeStr); - } + } } else { @@ -287,7 +278,7 @@ class RecyclerCheckerConsumer : public ASTConsumer mainVisitor.Inspect(); } - + private: CompilerInstance& _instance; }; @@ -311,9 +302,9 @@ class RecyclerCheckerAction : public PluginASTAction { { llvm::errs()<<"Help for RecyclerChecker plugin goes here\n"; } - + return true; - } + } }; } diff --git a/tools/RecyclerChecker/RecyclerChecker.def b/tools/RecyclerChecker/RecyclerChecker.def index 1dc5f546f27..ce84fcaa372 100644 --- a/tools/RecyclerChecker/RecyclerChecker.def +++ b/tools/RecyclerChecker/RecyclerChecker.def @@ -1,5 +1,5 @@ -LIBRARY PHPChecker -VERSION 1.0 +LIBRARY PHPChecker +VERSION 1.0 EXPORTS - clang_registerCheckers - clang_analyzerAPIVersionString + clang_registerCheckers + clang_analyzerAPIVersionString diff --git a/tools/RecyclerChecker/build.sh b/tools/RecyclerChecker/build.sh old mode 100644 new mode 100755 index d51a53a4a24..5067bb0a3d0 --- a/tools/RecyclerChecker/build.sh +++ b/tools/RecyclerChecker/build.sh @@ -1,5 +1,21 @@ +#!/bin/bash +#------------------------------------------------------------------------------------------------------- +# Copyright (C) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +#------------------------------------------------------------------------------------------------------- + +pushd `dirname $0` mkdir Build pushd Build -cmake -DCLANG_INCLUDE_DIRS:STRING=/usr/include/clang/3.8/ -DLLVM_CONFIG_EXECUTABLE:STRING=/usr/bin/llvm-config-3.8 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ .. + +cmake \ + -DCLANG_INCLUDE_DIRS:STRING=/usr/include/clang/3.8/ \ + -DLLVM_CONFIG_EXECUTABLE:STRING=/usr/bin/llvm-config-3.8 \ + -DCMAKE_C_COMPILER=/usr/bin/gcc \ + -DCMAKE_CXX_COMPILER=/usr/bin/g++ \ + -DCMAKE_BUILD_TYPE=Debug \ + .. make + +popd popd