Merge pull request #7 from dumganhar/iss1686-synchronize

fix for conflict of project.pbxproj and updated with upstream.
This commit is contained in:
minggo 2013-02-27 21:43:17 -08:00
commit 47830a5ef4
172 changed files with 6753 additions and 15133 deletions

View File

@ -0,0 +1,342 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
41E01E4E16D5D5E600ED686C /* Export.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4116D5D5E600ED686C /* Export.h */; };
41E01E4F16D5D5E600ED686C /* SimpleAudioEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4216D5D5E600ED686C /* SimpleAudioEngine.h */; };
41E01E5016D5D5E600ED686C /* CDAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4416D5D5E600ED686C /* CDAudioManager.h */; };
41E01E5116D5D5E600ED686C /* CDAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 41E01E4516D5D5E600ED686C /* CDAudioManager.m */; };
41E01E5216D5D5E600ED686C /* CDConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4616D5D5E600ED686C /* CDConfig.h */; };
41E01E5316D5D5E600ED686C /* CDOpenALSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4716D5D5E600ED686C /* CDOpenALSupport.h */; };
41E01E5416D5D5E600ED686C /* CDOpenALSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 41E01E4816D5D5E600ED686C /* CDOpenALSupport.m */; };
41E01E5516D5D5E600ED686C /* CocosDenshion.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4916D5D5E600ED686C /* CocosDenshion.h */; };
41E01E5616D5D5E600ED686C /* CocosDenshion.m in Sources */ = {isa = PBXBuildFile; fileRef = 41E01E4A16D5D5E600ED686C /* CocosDenshion.m */; };
41E01E5716D5D5E600ED686C /* SimpleAudioEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41E01E4B16D5D5E600ED686C /* SimpleAudioEngine.mm */; };
41E01E5816D5D5E600ED686C /* SimpleAudioEngine_objc.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E01E4C16D5D5E600ED686C /* SimpleAudioEngine_objc.h */; };
41E01E5916D5D5E600ED686C /* SimpleAudioEngine_objc.m in Sources */ = {isa = PBXBuildFile; fileRef = 41E01E4D16D5D5E600ED686C /* SimpleAudioEngine_objc.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
41E01E4116D5D5E600ED686C /* Export.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Export.h; sourceTree = "<group>"; };
41E01E4216D5D5E600ED686C /* SimpleAudioEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleAudioEngine.h; sourceTree = "<group>"; };
41E01E4416D5D5E600ED686C /* CDAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDAudioManager.h; sourceTree = "<group>"; };
41E01E4516D5D5E600ED686C /* CDAudioManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDAudioManager.m; sourceTree = "<group>"; };
41E01E4616D5D5E600ED686C /* CDConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDConfig.h; sourceTree = "<group>"; };
41E01E4716D5D5E600ED686C /* CDOpenALSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDOpenALSupport.h; sourceTree = "<group>"; };
41E01E4816D5D5E600ED686C /* CDOpenALSupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDOpenALSupport.m; sourceTree = "<group>"; };
41E01E4916D5D5E600ED686C /* CocosDenshion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocosDenshion.h; sourceTree = "<group>"; };
41E01E4A16D5D5E600ED686C /* CocosDenshion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CocosDenshion.m; sourceTree = "<group>"; };
41E01E4B16D5D5E600ED686C /* SimpleAudioEngine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SimpleAudioEngine.mm; sourceTree = "<group>"; };
41E01E4C16D5D5E600ED686C /* SimpleAudioEngine_objc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleAudioEngine_objc.h; sourceTree = "<group>"; };
41E01E4D16D5D5E600ED686C /* SimpleAudioEngine_objc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleAudioEngine_objc.m; sourceTree = "<group>"; };
D87CC2E5154FC6C500AAFE11 /* libCocosDenshion.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCocosDenshion.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D87CC2E2154FC6C500AAFE11 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4193AF8416C39EB1007E21D7 /* CocosDenshion */ = {
isa = PBXGroup;
children = (
41E01E4016D5D5E600ED686C /* include */,
41E01E4316D5D5E600ED686C /* ios */,
);
name = CocosDenshion;
sourceTree = "<group>";
};
41E01E4016D5D5E600ED686C /* include */ = {
isa = PBXGroup;
children = (
41E01E4116D5D5E600ED686C /* Export.h */,
41E01E4216D5D5E600ED686C /* SimpleAudioEngine.h */,
);
name = include;
path = ../include;
sourceTree = "<group>";
};
41E01E4316D5D5E600ED686C /* ios */ = {
isa = PBXGroup;
children = (
41E01E4416D5D5E600ED686C /* CDAudioManager.h */,
41E01E4516D5D5E600ED686C /* CDAudioManager.m */,
41E01E4616D5D5E600ED686C /* CDConfig.h */,
41E01E4716D5D5E600ED686C /* CDOpenALSupport.h */,
41E01E4816D5D5E600ED686C /* CDOpenALSupport.m */,
41E01E4916D5D5E600ED686C /* CocosDenshion.h */,
41E01E4A16D5D5E600ED686C /* CocosDenshion.m */,
41E01E4B16D5D5E600ED686C /* SimpleAudioEngine.mm */,
41E01E4C16D5D5E600ED686C /* SimpleAudioEngine_objc.h */,
41E01E4D16D5D5E600ED686C /* SimpleAudioEngine_objc.m */,
);
name = ios;
path = ../ios;
sourceTree = "<group>";
};
D87CC2BB154FC66100AAFE11 = {
isa = PBXGroup;
children = (
4193AF8416C39EB1007E21D7 /* CocosDenshion */,
D87CC2C9154FC66100AAFE11 /* Frameworks */,
D87CC2C7154FC66100AAFE11 /* Products */,
);
sourceTree = "<group>";
};
D87CC2C7154FC66100AAFE11 /* Products */ = {
isa = PBXGroup;
children = (
D87CC2E5154FC6C500AAFE11 /* libCocosDenshion.a */,
);
name = Products;
sourceTree = "<group>";
};
D87CC2C9154FC66100AAFE11 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D87CC2E3154FC6C500AAFE11 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
41E01E4E16D5D5E600ED686C /* Export.h in Headers */,
41E01E4F16D5D5E600ED686C /* SimpleAudioEngine.h in Headers */,
41E01E5016D5D5E600ED686C /* CDAudioManager.h in Headers */,
41E01E5216D5D5E600ED686C /* CDConfig.h in Headers */,
41E01E5316D5D5E600ED686C /* CDOpenALSupport.h in Headers */,
41E01E5516D5D5E600ED686C /* CocosDenshion.h in Headers */,
41E01E5816D5D5E600ED686C /* SimpleAudioEngine_objc.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D87CC2E4154FC6C500AAFE11 /* CocosDenshion */ = {
isa = PBXNativeTarget;
buildConfigurationList = D87CC2ED154FC6C500AAFE11 /* Build configuration list for PBXNativeTarget "CocosDenshion" */;
buildPhases = (
D87CC2E1154FC6C500AAFE11 /* Sources */,
D87CC2E2154FC6C500AAFE11 /* Frameworks */,
D87CC2E3154FC6C500AAFE11 /* Headers */,
185ADB8915A3935900CD7CE0 /* ShellScript */,
);
buildRules = (
);
dependencies = (
);
name = CocosDenshion;
productName = SPII;
productReference = D87CC2E5154FC6C500AAFE11 /* libCocosDenshion.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D87CC2BD154FC66100AAFE11 /* Project object */ = {
isa = PBXProject;
attributes = {
CLASSPREFIX = SP;
LastUpgradeCheck = 0430;
ORGANIZATIONNAME = Cocoachina;
};
buildConfigurationList = D87CC2C0154FC66100AAFE11 /* Build configuration list for PBXProject "CocosDenshion" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
"zh-Hans",
"zh-Hant",
);
mainGroup = D87CC2BB154FC66100AAFE11;
productRefGroup = D87CC2C7154FC66100AAFE11 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D87CC2E4154FC6C500AAFE11 /* CocosDenshion */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
185ADB8915A3935900CD7CE0 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D87CC2E1154FC6C500AAFE11 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
41E01E5116D5D5E600ED686C /* CDAudioManager.m in Sources */,
41E01E5416D5D5E600ED686C /* CDOpenALSupport.m in Sources */,
41E01E5616D5D5E600ED686C /* CocosDenshion.m in Sources */,
41E01E5716D5D5E600ED686C /* SimpleAudioEngine.mm in Sources */,
41E01E5916D5D5E600ED686C /* SimpleAudioEngine_objc.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
D87CC2DC154FC66100AAFE11 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = c89;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = armv7;
};
name = Debug;
};
D87CC2DD154FC66100AAFE11 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "compiler-default";
CLANG_CXX_LIBRARY = "compiler-default";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = c89;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = "";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = armv7;
};
name = Release;
};
D87CC2EE154FC6C500AAFE11 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
DSTROOT = /tmp/SPII.dst;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"COCOS2D_DEBUG=1",
CC_TARGET_OS_IPHONE,
);
GENERATE_PKGINFO_FILE = NO;
HEADER_SEARCH_PATHS = "\"$(SDKROOT)/usr/include/libxml2\"";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
LIBRARY_SEARCH_PATHS = "";
OTHER_LDFLAGS = "-ObjC";
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include;
PRODUCT_NAME = CocosDenshion;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "../../cocos2dx/platform/ios ../../cocos2dx/include ../../cocos2dx/kazmath/include ../../cocos2dx/";
VALID_ARCHS = armv7;
};
name = Debug;
};
D87CC2EF154FC6C500AAFE11 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
DSTROOT = /tmp/SPII.dst;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_C_LANGUAGE_STANDARD = "compiler-default";
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_PREFIX_HEADER = "";
GCC_PREPROCESSOR_DEFINITIONS = CC_TARGET_OS_IPHONE;
GENERATE_PKGINFO_FILE = NO;
HEADER_SEARCH_PATHS = "\"$(SDKROOT)/usr/include/libxml2\"";
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
LIBRARY_SEARCH_PATHS = "";
OTHER_LDFLAGS = "-ObjC";
PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include;
PRODUCT_NAME = CocosDenshion;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "../../cocos2dx/platform/ios ../../cocos2dx/include ../../cocos2dx/kazmath/include ../../cocos2dx/";
VALID_ARCHS = armv7;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D87CC2C0154FC66100AAFE11 /* Build configuration list for PBXProject "CocosDenshion" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D87CC2DC154FC66100AAFE11 /* Debug */,
D87CC2DD154FC66100AAFE11 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D87CC2ED154FC6C500AAFE11 /* Build configuration list for PBXNativeTarget "CocosDenshion" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D87CC2EE154FC6C500AAFE11 /* Debug */,
D87CC2EF154FC6C500AAFE11 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D87CC2BD154FC66100AAFE11 /* Project object */;
}

View File

@ -106,6 +106,7 @@ sprite_nodes/CCSprite.cpp \
sprite_nodes/CCSpriteBatchNode.cpp \
sprite_nodes/CCSpriteFrame.cpp \
sprite_nodes/CCSpriteFrameCache.cpp \
support/ccUTF8.cpp \
support/CCNotificationCenter.cpp \
support/CCProfiling.cpp \
support/CCPointExtension.cpp \

View File

@ -210,6 +210,7 @@ THE SOFTWARE.
#include "sprite_nodes/CCSpriteFrameCache.h"
// support
#include "support/ccUTF8.h"
#include "support/CCNotificationCenter.h"
#include "support/CCPointExtension.h"
#include "support/CCProfiling.h"

View File

@ -41,313 +41,12 @@ http://www.angelcode.com/products/bmfont/ (Free, Windows only)
#include "platform/CCFileUtils.h"
#include "CCDirector.h"
#include "textures/CCTextureCache.h"
#include "support/ccUTF8.h"
using namespace std;
NS_CC_BEGIN
static int cc_wcslen(const unsigned short* str)
{
int i=0;
while(*str++) i++;
return i;
}
/* Code from GLIB gutf8.c starts here. */
#define UTF8_COMPUTE(Char, Mask, Len) \
if (Char < 128) \
{ \
Len = 1; \
Mask = 0x7f; \
} \
else if ((Char & 0xe0) == 0xc0) \
{ \
Len = 2; \
Mask = 0x1f; \
} \
else if ((Char & 0xf0) == 0xe0) \
{ \
Len = 3; \
Mask = 0x0f; \
} \
else if ((Char & 0xf8) == 0xf0) \
{ \
Len = 4; \
Mask = 0x07; \
} \
else if ((Char & 0xfc) == 0xf8) \
{ \
Len = 5; \
Mask = 0x03; \
} \
else if ((Char & 0xfe) == 0xfc) \
{ \
Len = 6; \
Mask = 0x01; \
} \
else \
Len = -1;
#define UTF8_LENGTH(Char) \
((Char) < 0x80 ? 1 : \
((Char) < 0x800 ? 2 : \
((Char) < 0x10000 ? 3 : \
((Char) < 0x200000 ? 4 : \
((Char) < 0x4000000 ? 5 : 6)))))
#define UTF8_GET(Result, Chars, Count, Mask, Len) \
(Result) = (Chars)[0] & (Mask); \
for ((Count) = 1; (Count) < (Len); ++(Count)) \
{ \
if (((Chars)[(Count)] & 0xc0) != 0x80) \
{ \
(Result) = -1; \
break; \
} \
(Result) <<= 6; \
(Result) |= ((Chars)[(Count)] & 0x3f); \
}
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFE) != 0xFFFE)
static const char utf8_skip_data[256] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 6, 6, 1, 1
};
static const char *const g_utf8_skip = utf8_skip_data;
#define cc_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(unsigned char *)(p)])
/*
* @str: the string to search through.
* @c: the character to find.
*
* Returns the index of the first occurrence of the character, if found. Otherwise -1 is returned.
*
* Return value: the index of the first occurrence of the character if found or -1 otherwise.
* */
static unsigned int cc_utf8_find_char(std::vector<unsigned short> str, unsigned short c)
{
unsigned int len = str.size();
for (unsigned int i = 0; i < len; ++i)
if (str[i] == c) return i;
return -1;
}
/*
* @str: the string to search through.
* @c: the character to not look for.
*
* Return value: the index of the last character that is not c.
* */
static unsigned int cc_utf8_find_last_not_char(std::vector<unsigned short> str, unsigned short c)
{
int len = str.size();
int i = len - 1;
for (; i >= 0; --i)
if (str[i] != c) return i;
return i;
}
/*
* @str: the string to trim
* @index: the index to start trimming from.
*
* Trims str st str=[0, index) after the operation.
*
* Return value: the trimmed string.
* */
static void cc_utf8_trim_from(std::vector<unsigned short>* str, int index)
{
int size = str->size();
if (index >= size || index < 0)
return;
str->erase(str->begin() + index, str->begin() + size);
}
/*
* @ch is the unicode character whitespace?
*
* Reference: http://en.wikipedia.org/wiki/Whitespace_character#Unicode
*
* Return value: weather the character is a whitespace character.
* */
static bool isspace_unicode(unsigned short ch)
{
return (ch >= 0x0009 && ch <= 0x000D) || ch == 0x0020 || ch == 0x0085 || ch == 0x00A0 || ch == 0x1680
|| (ch >= 0x2000 && ch <= 0x200A) || ch == 0x2028 || ch == 0x2029 || ch == 0x202F
|| ch == 0x205F || ch == 0x3000;
}
static void cc_utf8_trim_ws(std::vector<unsigned short>* str)
{
int len = str->size();
if ( len <= 0 )
return;
int last_index = len - 1;
// Only start trimming if the last character is whitespace..
if (isspace_unicode((*str)[last_index]))
{
for (int i = last_index - 1; i >= 0; --i)
{
if (isspace_unicode((*str)[i]))
last_index = i;
else
break;
}
cc_utf8_trim_from(str, last_index);
}
}
/*
* g_utf8_strlen:
* @p: pointer to the start of a UTF-8 encoded string.
* @max: the maximum number of bytes to examine. If @max
* is less than 0, then the string is assumed to be
* null-terminated. If @max is 0, @p will not be examined and
* may be %NULL.
*
* Returns the length of the string in characters.
*
* Return value: the length of the string in characters
**/
CC_DLL long
cc_utf8_strlen (const char * p, int max)
{
long len = 0;
const char *start = p;
if (!(p != NULL || max == 0))
{
return 0;
}
if (max < 0)
{
while (*p)
{
p = cc_utf8_next_char (p);
++len;
}
}
else
{
if (max == 0 || !*p)
return 0;
p = cc_utf8_next_char (p);
while (p - start < max && *p)
{
++len;
p = cc_utf8_next_char (p);
}
/* only do the last len increment if we got a complete
* char (don't count partial chars)
*/
if (p - start == max)
++len;
}
return len;
}
/*
* g_utf8_get_char:
* @p: a pointer to Unicode character encoded as UTF-8
*
* Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
* If @p does not point to a valid UTF-8 encoded character, results are
* undefined. If you are not sure that the bytes are complete
* valid Unicode characters, you should use g_utf8_get_char_validated()
* instead.
*
* Return value: the resulting character
**/
static unsigned int
cc_utf8_get_char (const char * p)
{
int i, mask = 0, len;
unsigned int result;
unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len);
if (len == -1)
return (unsigned int) - 1;
UTF8_GET (result, p, i, mask, len);
return result;
}
/*
* cc_utf16_from_utf8:
* @str_old: pointer to the start of a C string.
*
* Creates a utf8 string from a cstring.
*
* Return value: the newly created utf8 string.
* */
static unsigned short* cc_utf16_from_utf8(const char* str_old)
{
int len = cc_utf8_strlen(str_old, -1);
unsigned short* str_new = new unsigned short[len + 1];
str_new[len] = 0;
for (int i = 0; i < len; ++i)
{
str_new[i] = cc_utf8_get_char(str_old);
str_old = cc_utf8_next_char(str_old);
}
return str_new;
}
static std::vector<unsigned short> cc_utf16_vec_from_utf16_str(const unsigned short* str)
{
int len = cc_wcslen(str);
std::vector<unsigned short> str_new;
for (int i = 0; i < len; ++i)
{
str_new.push_back(str[i]);
}
return str_new;
}
//
//FNTConfig Cache - free functions
//
@ -1017,7 +716,7 @@ void CCLabelBMFont::setString(const char *newString)
void CCLabelBMFont::setString(const char *newString, bool fromUpdate)
{
CC_SAFE_DELETE_ARRAY(m_sString);
m_sString = cc_utf16_from_utf8(newString);
m_sString = cc_utf8_to_utf16(newString);
// MARMALADE CHANGE
// THE ASSIGMENT OF STRINGS BELOW PERFORMS AN OVERLAPPING MEMCPY, WHEN fromUpdate IS TRUE

View File

@ -1 +1 @@
07189afafe45b5ce86fe17e77400ffa055cd1831
8e581cccdac41ebd5f1a9c26b08f02b948560fba

View File

@ -104,6 +104,7 @@ OBJECTS = ../actions/CCAction.o \
../sprite_nodes/CCSpriteBatchNode.o \
../sprite_nodes/CCSpriteFrame.o \
../sprite_nodes/CCSpriteFrameCache.o \
../support/ccUTF8.o \
../support/CCPointExtension.o \
../support/CCProfiling.o \
../support/CCUserDefault.o \

View File

@ -1 +1 @@
4f8a2ffda386a2d2e263781a283c32d39b6dc6a7
cc07100d26f9435ecf7b2588f14adb3d22980883

View File

@ -157,34 +157,28 @@ files
"*.h"
"*.cpp"
("../support")
[support]
"base64.cpp"
"base64.h"
# "CCArray.cpp"
"CCPointExtension.cpp"
"CCProfiling.cpp"
"CCProfiling.h"
"CCUserDefault.cpp"
"ccUtils.cpp"
"ccUtils.h"
"TransformUtils.cpp"
"TransformUtils.h"
("../support")
[support]
"*.h"
"*.cpp"
("../support/data_support")
[support/data_support]
"*.cpp" # MH: Many ccCArray linker errors without ccCArray.cpp
"*.h"
("../support/image_support")
[support/image_support]
"*.h"
"*.cpp"
("../support/tinyxml2")
[support/tinyxml2]
"*.h"
"*.cpp"
("../support/zip_support")
[support/zip_support]
"*.h"
"*.cpp"

View File

@ -215,6 +215,7 @@ xcopy /Y /Q "$(ProjectDir)..\platform\third_party\win32\libraries\*.*" "$(OutDir
<ClCompile Include="..\support\CCPointExtension.cpp" />
<ClCompile Include="..\support\CCProfiling.cpp" />
<ClCompile Include="..\support\CCUserDefault.cpp" />
<ClCompile Include="..\support\ccUTF8.cpp" />
<ClCompile Include="..\support\ccUtils.cpp" />
<ClCompile Include="..\support\CCVertex.cpp" />
<ClCompile Include="..\support\tinyxml2\tinyxml2.cpp" />
@ -366,6 +367,7 @@ xcopy /Y /Q "$(ProjectDir)..\platform\third_party\win32\libraries\*.*" "$(OutDir
<ClInclude Include="..\support\CCPointExtension.h" />
<ClInclude Include="..\support\CCProfiling.h" />
<ClInclude Include="..\support\CCUserDefault.h" />
<ClInclude Include="..\support\ccUTF8.h" />
<ClInclude Include="..\support\ccUtils.h" />
<ClInclude Include="..\support\CCVertex.h" />
<ClInclude Include="..\support\tinyxml2\tinyxml2.h" />

View File

@ -450,6 +450,9 @@
<ClCompile Include="..\platform\win32\CCDevice.cpp">
<Filter>platform\win32</Filter>
</ClCompile>
<ClCompile Include="..\support\ccUTF8.cpp">
<Filter>support</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\base_nodes\CCAtlasNode.h">
@ -901,5 +904,8 @@
<Filter>platform\win32</Filter>
</ClInclude>
<ClInclude Include="..\support\tinyxml2\tinyxml2.h" />
<ClInclude Include="..\support\ccUTF8.h">
<Filter>support</Filter>
</ClInclude>
</ItemGroup>
</Project>

529
cocos2dx/support/ccUTF8.cpp Normal file
View File

@ -0,0 +1,529 @@
/*
* This file uses some implementations of gutf8.c in glib.
*
* gutf8.c - Operations on UTF-8 strings.
*
* Copyright (C) 1999 Tom Tromey
* Copyright (C) 2000 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "ccUTF8.h"
#include "platform/CCCommon.h"
NS_CC_BEGIN
int cc_wcslen(const unsigned short* str)
{
int i=0;
while(*str++) i++;
return i;
}
/* Code from GLIB gutf8.c starts here. */
#define UTF8_COMPUTE(Char, Mask, Len) \
if (Char < 128) \
{ \
Len = 1; \
Mask = 0x7f; \
} \
else if ((Char & 0xe0) == 0xc0) \
{ \
Len = 2; \
Mask = 0x1f; \
} \
else if ((Char & 0xf0) == 0xe0) \
{ \
Len = 3; \
Mask = 0x0f; \
} \
else if ((Char & 0xf8) == 0xf0) \
{ \
Len = 4; \
Mask = 0x07; \
} \
else if ((Char & 0xfc) == 0xf8) \
{ \
Len = 5; \
Mask = 0x03; \
} \
else if ((Char & 0xfe) == 0xfc) \
{ \
Len = 6; \
Mask = 0x01; \
} \
else \
Len = -1;
#define UTF8_LENGTH(Char) \
((Char) < 0x80 ? 1 : \
((Char) < 0x800 ? 2 : \
((Char) < 0x10000 ? 3 : \
((Char) < 0x200000 ? 4 : \
((Char) < 0x4000000 ? 5 : 6)))))
#define UTF8_GET(Result, Chars, Count, Mask, Len) \
(Result) = (Chars)[0] & (Mask); \
for ((Count) = 1; (Count) < (Len); ++(Count)) \
{ \
if (((Chars)[(Count)] & 0xc0) != 0x80) \
{ \
(Result) = -1; \
break; \
} \
(Result) <<= 6; \
(Result) |= ((Chars)[(Count)] & 0x3f); \
}
#define UNICODE_VALID(Char) \
((Char) < 0x110000 && \
(((Char) & 0xFFFFF800) != 0xD800) && \
((Char) < 0xFDD0 || (Char) > 0xFDEF) && \
((Char) & 0xFFFE) != 0xFFFE)
static const char utf8_skip_data[256] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 6, 6, 1, 1
};
static const char *const g_utf8_skip = utf8_skip_data;
#define cc_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(unsigned char *)(p)])
/*
* @str: the string to search through.
* @c: the character to find.
*
* Returns the index of the first occurrence of the character, if found. Otherwise -1 is returned.
*
* Return value: the index of the first occurrence of the character if found or -1 otherwise.
* */
static unsigned int cc_utf8_find_char(std::vector<unsigned short> str, unsigned short c)
{
unsigned int len = str.size();
for (unsigned int i = 0; i < len; ++i)
if (str[i] == c) return i;
return -1;
}
/*
* @str: the string to search through.
* @c: the character to not look for.
*
* Return value: the index of the last character that is not c.
* */
unsigned int cc_utf8_find_last_not_char(std::vector<unsigned short> str, unsigned short c)
{
int len = str.size();
int i = len - 1;
for (; i >= 0; --i)
if (str[i] != c) return i;
return i;
}
/*
* @str: the string to trim
* @index: the index to start trimming from.
*
* Trims str st str=[0, index) after the operation.
*
* Return value: the trimmed string.
* */
static void cc_utf8_trim_from(std::vector<unsigned short>* str, int index)
{
int size = str->size();
if (index >= size || index < 0)
return;
str->erase(str->begin() + index, str->begin() + size);
}
/*
* @ch is the unicode character whitespace?
*
* Reference: http://en.wikipedia.org/wiki/Whitespace_character#Unicode
*
* Return value: weather the character is a whitespace character.
* */
bool isspace_unicode(unsigned short ch)
{
return (ch >= 0x0009 && ch <= 0x000D) || ch == 0x0020 || ch == 0x0085 || ch == 0x00A0 || ch == 0x1680
|| (ch >= 0x2000 && ch <= 0x200A) || ch == 0x2028 || ch == 0x2029 || ch == 0x202F
|| ch == 0x205F || ch == 0x3000;
}
void cc_utf8_trim_ws(std::vector<unsigned short>* str)
{
int len = str->size();
if ( len <= 0 )
return;
int last_index = len - 1;
// Only start trimming if the last character is whitespace..
if (isspace_unicode((*str)[last_index]))
{
for (int i = last_index - 1; i >= 0; --i)
{
if (isspace_unicode((*str)[i]))
last_index = i;
else
break;
}
cc_utf8_trim_from(str, last_index);
}
}
/*
* cc_utf8_strlen:
* @p: pointer to the start of a UTF-8 encoded string.
* @max: the maximum number of bytes to examine. If @max
* is less than 0, then the string is assumed to be
* null-terminated. If @max is 0, @p will not be examined and
* may be %NULL.
*
* Returns the length of the string in characters.
*
* Return value: the length of the string in characters
**/
long
cc_utf8_strlen (const char * p, int max)
{
long len = 0;
const char *start = p;
if (!(p != NULL || max == 0))
{
return 0;
}
if (max < 0)
{
while (*p)
{
p = cc_utf8_next_char (p);
++len;
}
}
else
{
if (max == 0 || !*p)
return 0;
p = cc_utf8_next_char (p);
while (p - start < max && *p)
{
++len;
p = cc_utf8_next_char (p);
}
/* only do the last len increment if we got a complete
* char (don't count partial chars)
*/
if (p - start == max)
++len;
}
return len;
}
/*
* g_utf8_get_char:
* @p: a pointer to Unicode character encoded as UTF-8
*
* Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
* If @p does not point to a valid UTF-8 encoded character, results are
* undefined. If you are not sure that the bytes are complete
* valid Unicode characters, you should use g_utf8_get_char_validated()
* instead.
*
* Return value: the resulting character
**/
static unsigned int
cc_utf8_get_char (const char * p)
{
int i, mask = 0, len;
unsigned int result;
unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len);
if (len == -1)
return (unsigned int) - 1;
UTF8_GET (result, p, i, mask, len);
return result;
}
unsigned short* cc_utf8_to_utf16(const char* str_old)
{
int len = cc_utf8_strlen(str_old, -1);
unsigned short* str_new = new unsigned short[len + 1];
str_new[len] = 0;
for (int i = 0; i < len; ++i)
{
str_new[i] = cc_utf8_get_char(str_old);
str_old = cc_utf8_next_char(str_old);
}
return str_new;
}
std::vector<unsigned short> cc_utf16_vec_from_utf16_str(const unsigned short* str)
{
int len = cc_wcslen(str);
std::vector<unsigned short> str_new;
for (int i = 0; i < len; ++i)
{
str_new.push_back(str[i]);
}
return str_new;
}
/**
* cc_unichar_to_utf8:
* @c: a ISO10646 character code
* @outbuf: output buffer, must have at least 6 bytes of space.
* If %NULL, the length will be computed and returned
* and nothing will be written to @outbuf.
*
* Converts a single character to UTF-8.
*
* Return value: number of bytes written
**/
int
cc_unichar_to_utf8 (unsigned short c,
char *outbuf)
{
unsigned int len = 0;
int first;
int i;
if (c < 0x80)
{
first = 0;
len = 1;
}
else if (c < 0x800)
{
first = 0xc0;
len = 2;
}
else if (c < 0x10000)
{
first = 0xe0;
len = 3;
}
else if (c < 0x200000)
{
first = 0xf0;
len = 4;
}
else if (c < 0x4000000)
{
first = 0xf8;
len = 5;
}
else
{
first = 0xfc;
len = 6;
}
if (outbuf)
{
for (i = len - 1; i > 0; --i)
{
outbuf[i] = (c & 0x3f) | 0x80;
c >>= 6;
}
outbuf[0] = c | first;
}
return len;
}
#define SURROGATE_VALUE(h,l) (((h) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000)
/**
* cc_utf16_to_utf8:
* @str: a UTF-16 encoded string
* @len: the maximum length of @str to use. If @len < 0, then
* the string is terminated with a 0 character.
* @items_read: location to store number of words read, or %NULL.
* If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
* returned in case @str contains a trailing partial
* character. If an error occurs then the index of the
* invalid input is stored here.
* @items_written: location to store number of bytes written, or %NULL.
* The value stored here does not include the trailing
* 0 byte.
* @error: location to store the error occuring, or %NULL to ignore
* errors. Any of the errors in #GConvertError other than
* %G_CONVERT_ERROR_NO_CONVERSION may occur.
*
* Convert a string from UTF-16 to UTF-8. The result will be
* terminated with a 0 byte.
*
* Return value: a pointer to a newly allocated UTF-8 string.
* This value must be freed with free(). If an
* error occurs, %NULL will be returned and
* @error set.
**/
char *
cc_utf16_to_utf8 (const unsigned short *str,
long len,
long *items_read,
long *items_written)
{
/* This function and g_utf16_to_ucs4 are almost exactly identical - The lines that differ
* are marked.
*/
const unsigned short *in;
char *out;
char *result = NULL;
int n_bytes;
unsigned short high_surrogate;
if (str == 0) return NULL;
n_bytes = 0;
in = str;
high_surrogate = 0;
while ((len < 0 || in - str < len) && *in)
{
unsigned short c = *in;
unsigned short wc;
if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
{
if (high_surrogate)
{
wc = SURROGATE_VALUE (high_surrogate, c);
high_surrogate = 0;
}
else
{
CCLOGERROR("Invalid sequence in conversion input");
goto err_out;
}
}
else
{
if (high_surrogate)
{
CCLOGERROR("Invalid sequence in conversion input");
goto err_out;
}
if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
{
high_surrogate = c;
goto next1;
}
else
wc = c;
}
/********** DIFFERENT for UTF8/UCS4 **********/
n_bytes += UTF8_LENGTH (wc);
next1:
in++;
}
if (high_surrogate && !items_read)
{
CCLOGERROR("Partial character sequence at end of input");
goto err_out;
}
/* At this point, everything is valid, and we just need to convert
*/
/********** DIFFERENT for UTF8/UCS4 **********/
result = new char[n_bytes + 1];
high_surrogate = 0;
out = result;
in = str;
while (out < result + n_bytes)
{
unsigned short c = *in;
unsigned short wc;
if (c >= 0xdc00 && c < 0xe000) /* low surrogate */
{
wc = SURROGATE_VALUE (high_surrogate, c);
high_surrogate = 0;
}
else if (c >= 0xd800 && c < 0xdc00) /* high surrogate */
{
high_surrogate = c;
goto next2;
}
else
wc = c;
/********** DIFFERENT for UTF8/UCS4 **********/
out += cc_unichar_to_utf8 (wc, out);
next2:
in++;
}
/********** DIFFERENT for UTF8/UCS4 **********/
*out = '\0';
if (items_written)
/********** DIFFERENT for UTF8/UCS4 **********/
*items_written = out - result;
err_out:
if (items_read)
*items_read = in - str;
return result;
}
NS_CC_END

97
cocos2dx/support/ccUTF8.h Normal file
View File

@ -0,0 +1,97 @@
//
// ccUTF8.h
// cocos2dx
//
// Created by James Chen on 2/27/13.
//
#ifndef __cocos2dx__ccUTF8__
#define __cocos2dx__ccUTF8__
#include "platform/CCPlatformMacros.h"
#include <vector>
NS_CC_BEGIN
CC_DLL int cc_wcslen(const unsigned short* str);
CC_DLL void cc_utf8_trim_ws(std::vector<unsigned short>* str);
/*
* @ch is the unicode character whitespace?
*
* Reference: http://en.wikipedia.org/wiki/Whitespace_character#Unicode
*
* Return value: weather the character is a whitespace character.
* */
CC_DLL bool isspace_unicode(unsigned short ch);
/*
* cc_utf8_strlen:
* @p: pointer to the start of a UTF-8 encoded string.
* @max: the maximum number of bytes to examine. If @max
* is less than 0, then the string is assumed to be
* null-terminated. If @max is 0, @p will not be examined and
* may be %NULL.
*
* Returns the length of the string in characters.
*
* Return value: the length of the string in characters
**/
CC_DLL long
cc_utf8_strlen (const char * p, int max);
/*
* @str: the string to search through.
* @c: the character to not look for.
*
* Return value: the index of the last character that is not c.
* */
CC_DLL unsigned int cc_utf8_find_last_not_char(std::vector<unsigned short> str, unsigned short c);
CC_DLL std::vector<unsigned short> cc_utf16_vec_from_utf16_str(const unsigned short* str);
/*
* cc_utf8_to_utf16:
* @str_old: pointer to the start of a C string.
*
* Creates a utf8 string from a cstring.
*
* Return value: the newly created utf8 string.
* */
CC_DLL unsigned short* cc_utf8_to_utf16(const char* str_old);
/**
* cc_utf16_to_utf8:
* @str: a UTF-16 encoded string
* @len: the maximum length of @str to use. If @len < 0, then
* the string is terminated with a 0 character.
* @items_read: location to store number of words read, or %NULL.
* If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be
* returned in case @str contains a trailing partial
* character. If an error occurs then the index of the
* invalid input is stored here.
* @items_written: location to store number of bytes written, or %NULL.
* The value stored here does not include the trailing
* 0 byte.
* @error: location to store the error occuring, or %NULL to ignore
* errors. Any of the errors in #GConvertError other than
* %G_CONVERT_ERROR_NO_CONVERSION may occur.
*
* Convert a string from UTF-16 to UTF-8. The result will be
* terminated with a 0 byte.
*
* Return value: a pointer to a newly allocated UTF-8 string.
* This value must be freed with free(). If an
* error occurs, %NULL will be returned and
* @error set.
**/
CC_DLL char *
cc_utf16_to_utf8 (const unsigned short *str,
long len,
long *items_read,
long *items_written);
NS_CC_END
#endif /* defined(__cocos2dx__ccUTF8__) */

View File

@ -31,11 +31,6 @@
#include "jni/Java_org_cocos2dx_lib_Cocos2dxBitmap.h"
#include "jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"
// This function is implemented in CCLabelBMFont.cpp
NS_CC_BEGIN
extern long cc_utf8_strlen (const char * p, int max);
NS_CC_END
NS_CC_EXT_BEGIN

View File

@ -29,10 +29,6 @@
#include "CCEditBox.h"
#include "proj.win32/Win32InputBox.h"
NS_CC_BEGIN
extern CC_DLL long cc_utf8_strlen (const char * p, int max);
NS_CC_END
NS_CC_EXT_BEGIN
CCEditBoxImpl* __createSystemEditBox(CCEditBox* pEditBox)

View File

@ -101,6 +101,7 @@ CCTableViewVerticalFillOrder CCTableView::getVerticalFillOrder()
void CCTableView::reloadData()
{
m_eOldDirection = kCCScrollViewDirectionNone;
CCObject* pObj = NULL;
CCARRAY_FOREACH(m_pCellsUsed, pObj)
{

@ -1 +1 @@
Subproject commit cc6d8acc731c5a6970e96cc2ba231718ba693dfc
Subproject commit 0455fdce1ec89d6bf335e395b48882aaf875d38b

View File

@ -190,7 +190,7 @@ local function SpriteProgressToRadialMidpointChanged()
left:setType(kCCProgressTimerTypeRadial)
left:setMidpoint(CCPointMake(0.25, 0.75))
left:setPosition(CCPointMake(100, s.height / 2))
left:runAction(CCRepeatForever:create(action:copy():autorelease()))
left:runAction(CCRepeatForever:create(CCProgressTo:create(2, 100)))
layer:addChild(left)
-- Our image on the left should be a radial progress indicator, counter clockwise
@ -203,7 +203,7 @@ local function SpriteProgressToRadialMidpointChanged()
we get a counter clockwise progress.
]]
right:setPosition(CCPointMake(s.width - 100, s.height / 2))
right:runAction(CCRepeatForever:create(action:copy():autorelease()))
right:runAction(CCRepeatForever:create(CCProgressTo:create(2, 100)))
layer:addChild(right)
subtitleLabel:setString("Radial w/ Different Midpoints")
@ -227,7 +227,7 @@ local function SpriteProgressBarVarious()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
left:setBarChangeRate(CCPointMake(1, 0))
left:setPosition(CCPointMake(100, s.height / 2))
left:runAction(CCRepeatForever:create(to:copy():autorelease()))
left:runAction(CCRepeatForever:create(CCProgressTo:create(2, 100)))
layer:addChild(left)
local middle = CCProgressTimer:create(CCSprite:create(s_pPathSister2))
@ -237,7 +237,7 @@ local function SpriteProgressBarVarious()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
middle:setBarChangeRate(CCPointMake(1, 1))
middle:setPosition(CCPointMake(s.width/2, s.height/2))
middle:runAction(CCRepeatForever:create(to:copy():autorelease()))
middle:runAction(CCRepeatForever:create(CCProgressTo:create(2, 100)))
layer:addChild(middle)
local right = CCProgressTimer:create(CCSprite:create(s_pPathSister2))
@ -247,7 +247,7 @@ local function SpriteProgressBarVarious()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
right:setBarChangeRate(CCPointMake(0, 1))
right:setPosition(CCPointMake(s.width-100, s.height/2))
right:runAction(CCRepeatForever:create(to:copy():autorelease()))
right:runAction(CCRepeatForever:create(CCProgressTo:create(2, 100)))
layer:addChild(right)
subtitleLabel:setString("ProgressTo Bar Mid")
@ -279,8 +279,8 @@ local function SpriteProgressBarTintAndFade()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
left:setBarChangeRate(CCPointMake(1, 0))
left:setPosition(CCPointMake(100, s.height / 2))
left:runAction(CCRepeatForever:create(to:copy():autorelease()))
left:runAction(CCRepeatForever:create(tint:copy():autorelease()))
left:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
left:runAction(CCRepeatForever:create(CCSequence:create(array)))
layer:addChild(left)
left:addChild(CCLabelTTF:create("Tint", "Marker Felt", 20.0))
@ -292,8 +292,12 @@ local function SpriteProgressBarTintAndFade()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
middle:setBarChangeRate(CCPointMake(1, 1))
middle:setPosition(CCPointMake(s.width / 2, s.height / 2))
middle:runAction(CCRepeatForever:create(to:copy():autorelease()))
middle:runAction(CCRepeatForever:create(fade:copy():autorelease()))
middle:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
local fade2 = CCSequence:createWithTwoActions(
CCFadeTo:create(1.0, 0),
CCFadeTo:create(1.0, 255))
middle:runAction(CCRepeatForever:create(fade2))
layer:addChild(middle)
middle:addChild(CCLabelTTF:create("Fade", "Marker Felt", 20.0))
@ -305,9 +309,11 @@ local function SpriteProgressBarTintAndFade()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
right:setBarChangeRate(CCPointMake(0, 1))
right:setPosition(CCPointMake(s.width - 100, s.height / 2))
right:runAction(CCRepeatForever:create(to:copy():autorelease()))
right:runAction(CCRepeatForever:create(tint:copy():autorelease()))
right:runAction(CCRepeatForever:create(fade:copy():autorelease()))
right:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
right:runAction(CCRepeatForever:create(CCSequence:create(array)))
right:runAction(CCRepeatForever:create(CCSequence:createWithTwoActions(
CCFadeTo:create(1.0, 0),
CCFadeTo:create(1.0, 255))))
layer:addChild(right)
right:addChild(CCLabelTTF:create("Tint and Fade", "Marker Felt", 20.0))
@ -334,7 +340,7 @@ local function SpriteProgressWithSpriteFrame()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
left:setBarChangeRate(CCPointMake(1, 0))
left:setPosition(CCPointMake(100, s.height / 2))
left:runAction(CCRepeatForever:create(to:copy():autorelease()))
left:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
layer:addChild(left)
local middle = CCProgressTimer:create(CCSprite:createWithSpriteFrameName("grossini_dance_02.png"))
@ -344,7 +350,7 @@ local function SpriteProgressWithSpriteFrame()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
middle:setBarChangeRate(CCPointMake(1, 1))
middle:setPosition(CCPointMake(s.width / 2, s.height / 2))
middle:runAction(CCRepeatForever:create(to:copy():autorelease()))
middle:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
layer:addChild(middle)
local right = CCProgressTimer:create(CCSprite:createWithSpriteFrameName("grossini_dance_03.png"))
@ -354,7 +360,7 @@ local function SpriteProgressWithSpriteFrame()
-- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change
right:setBarChangeRate(CCPointMake(0, 1))
right:setPosition(CCPointMake(s.width - 100, s.height / 2))
right:runAction(CCRepeatForever:create(to:copy():autorelease()))
right:runAction(CCRepeatForever:create(CCProgressTo:create(6, 100)))
layer:addChild(right)
subtitleLabel:setString("Progress With Sprite Frame")

View File

@ -213,7 +213,9 @@ local function ActionRotate()
local actionByBack = actionBy:reverse()
grossini:runAction(CCSequence:createWithTwoActions(actionBy, actionByBack))
kathia:runAction(CCSequence:createWithTwoActions(actionTo2, actionTo0:copy():autorelease()))
local action0Retain = CCRotateTo:create(2 , 0)
kathia:runAction(CCSequence:createWithTwoActions(actionTo2, action0Retain))
subtitleLabel:setString("RotateTo / RotateBy")
return layer
@ -699,7 +701,9 @@ local function ActionRepeat()
local a1 = CCMoveBy:create(1, ccp(150,0))
local action1 = CCRepeat:create(CCSequence:createWithTwoActions(CCPlace:create(ccp(60,60)), a1), 3)
local action2 = CCRepeatForever:create(CCSequence:createWithTwoActions(a1:copy():autorelease(), a1:reverse()))
local a2 = CCMoveBy:create(1, ccp(150,0))
local action2 = CCRepeatForever:create(CCSequence:createWithTwoActions(a2, a1:reverse()))
kathia:runAction(action1)
tamara:runAction(action2)
@ -746,7 +750,8 @@ local function ActionRotateToRepeat()
local act2 = CCRotateTo:create(1, 0)
local seq = CCSequence:createWithTwoActions(act1, act2)
local rep1 = CCRepeatForever:create(seq)
local rep2 = CCRepeat:create(seq:copy():autorelease(), 10)
local seq2 = CCSequence:createWithTwoActions(act1, act2)
local rep2 = CCRepeat:create(seq2, 10)
tamara:runAction(rep1)
kathia:runAction(rep2)
@ -770,7 +775,12 @@ local function ActionRotateJerk()
CCRotateTo:create(0.5, 20))
local rep1 = CCRepeat:create(seq, 10)
local rep2 = CCRepeatForever:create(seq:copy():autorelease())
local seq2 = CCSequence:createWithTwoActions(
CCRotateTo:create(0.5, -20),
CCRotateTo:create(0.5, 20))
local rep2 = CCRepeatForever:create(seq2)
tamara:runAction(rep1)
kathia:runAction(rep2)
@ -932,8 +942,12 @@ local function ActionOrbit()
local seq = CCSequence:createWithTwoActions(move, move_back)
local rfe = CCRepeatForever:create(seq)
kathia:runAction(rfe)
tamara:runAction(rfe:copy():autorelease())
grossini:runAction(rfe:copy():autorelease())
local rfe2 = CCRepeatForever:create(seq)
tamara:runAction(rfe2)
local rfe3 = CCRepeatForever:create(seq)
grossini:runAction(rfe3)
subtitleLabel:setString("OrbitCamera action")
@ -973,9 +987,9 @@ local function ActionTargeted()
centerSprites(2)
local jump1 = CCJumpBy:create(2, ccp(0, 0), 100, 3)
local jump2 = jump1:copy():autorelease()
local jump2 = CCJumpBy:create(2, ccp(0, 0), 100, 3)
local rot1 = CCRotateBy:create(1, 360)
local rot2 = rot1:copy():autorelease()
local rot2 = CCRotateBy:create(1, 360)
local t1 = CCTargetedAction:create(kathia, jump2)
local t2 = CCTargetedAction:create(kathia, rot2)

View File

@ -164,7 +164,7 @@ end
-- ShakyTiles3DDemo
--------------------------------------
local function ShakyTiles3DDemo(t)
return CCShakyTiles3D:create(t, CCSizeMake(16,12), 5, false) ;
return CCShakyTiles3D:create(t, CCSizeMake(16,12), 5, false);
end
--------------------------------------

View File

@ -332,7 +332,8 @@ ScriptingCore::ScriptingCore()
, debugGlobal_(NULL)
{
// set utf8 strings internally (we don't need utf16)
JS_SetCStringsAreUTF8();
// XXX: Removed in SpiderMonkey 19.0
//JS_SetCStringsAreUTF8();
this->addRegisterCallback(registerDefaultClasses);
this->runLoop = new SimpleRunLoop();
}
@ -417,7 +418,7 @@ void ScriptingCore::createGlobalContext() {
this->rt_ = NULL;
}
//JS_SetCStringsAreUTF8();
this->rt_ = JS_NewRuntime(10 * 1024 * 1024);
this->rt_ = JS_NewRuntime(10 * 1024 * 1024, JS_NO_HELPER_THREADS);
this->cx_ = JS_NewContext(rt_, 10240);
JS_SetOptions(this->cx_, JSOPTION_TYPE_INFERENCE);
JS_SetVersion(this->cx_, JSVERSION_LATEST);
@ -456,17 +457,25 @@ JSBool ScriptingCore::runScript(const char *path, JSObject* global, JSContext* c
cx = cx_;
}
js::RootedObject obj(cx, global);
JS::CompileOptions options(cx);
options.setUTF8(true).setFileAndLine(rpath.c_str(), 1);
// this will always compile the script, we can actually check if the script
// was compiled before, because it can be in the global map
#ifdef ANDROID
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
unsigned char *content = NULL;
unsigned long contentSize = 0;
content = (unsigned char*)CCString::createWithContentsOfFile(rpath.c_str())->getCString();
contentSize = strlen((char*)content);
JSScript* script = JS_CompileScript(cx, global, (char*)content, contentSize, path, 1);
// Not supported in SpiderMonkey 19.0
//JSScript* script = JS_CompileScript(cx, global, (char*)content, contentSize, path, 1);
JSScript *script = JS::Compile(cx, obj, options, (char*)content, contentSize);
#else
JSScript* script = JS_CompileUTF8File(cx, global, rpath.c_str());
// Removed in SpiderMonkey 19.0
//JSScript* script = JS_CompileUTF8File(cx, global, rpath.c_str());
JSScript *script = JS::Compile(cx, obj, options, rpath.c_str());
#endif
JSBool evaluatedOK = false;
if (script) {
@ -963,15 +972,20 @@ JSBool jsval_to_uint16( JSContext *cx, jsval vp, uint16_t *outval )
return ok;
}
JSBool jsval_to_long_long(JSContext *cx, jsval v, long long* ret) {
JSBool ok = JS_TRUE;
JSObject *tmp = JSVAL_TO_OBJECT(v);
ok &= JS_IsTypedArrayObject(tmp, cx) && JS_GetTypedArrayByteLength(tmp, cx) == 8;
JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments");
JSBool jsval_to_long_long(JSContext *cx, jsval vp, long long* r) {
JSObject *tmp_arg;
JSBool ok = JS_ValueToObject( cx, vp, &tmp_arg );
JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error converting value to object");
JSB_PRECONDITION2( tmp_arg && JS_IsTypedArrayObject( tmp_arg ), cx, JS_FALSE, "Not a TypedArray object");
JSB_PRECONDITION2( JS_GetTypedArrayByteLength( tmp_arg ) == sizeof(long long), cx, JS_FALSE, "Invalid Typed Array length");
uint32_t *data = (uint32_t *)JS_GetUint32ArrayData(tmp, cx);
*ret = (long long)(*data);
return ok;
uint32_t* arg_array = (uint32_t*)JS_GetArrayBufferViewData( tmp_arg );
long long ret = arg_array[0];
ret = ret << 32;
ret |= arg_array[1];
*r = ret;
return JS_TRUE;
}
JSBool jsval_to_std_string(JSContext *cx, jsval v, std::string* ret) {
@ -1337,7 +1351,7 @@ jsval uint32_to_jsval( JSContext *cx, uint32_t number )
jsval long_long_to_jsval(JSContext* cx, long long v) {
JSObject *tmp = JS_NewUint32Array(cx, 2);
uint32_t *data = (uint32_t *)JS_GetArrayBufferViewData(tmp, cx);
uint32_t *data = (uint32_t *)JS_GetArrayBufferViewData(tmp);
data[0] = ((uint32_t *)(&v))[0];
data[1] = ((uint32_t *)(&v))[1];
return OBJECT_TO_JSVAL(tmp);
@ -1611,12 +1625,12 @@ JSBool JSBDebug_BufferWrite(JSContext* cx, unsigned argc, jsval* vp)
const char* str;
JSString* jsstr = JS_ValueToString(cx, argv[0]);
str = JS_EncodeString(cx, jsstr);
// Not supported in SpiderMonkey v19
//str = JS_EncodeString(cx, jsstr);
JSStringWrapper strWrapper(jsstr);
// this is safe because we're already inside a lock (from clearBuffers)
outData.append(str);
JS_free(cx, (void*)str);
outData.append(strWrapper.get());
}
return JS_TRUE;
}

View File

@ -267,16 +267,13 @@ public:
}
~JSStringWrapper() {
if (buffer) {
JS_free(ScriptingCore::getInstance()->getGlobalContext(), (void*)buffer);
// JS_free(ScriptingCore::getInstance()->getGlobalContext(), (void*)buffer);
CC_SAFE_DELETE_ARRAY(buffer);
}
}
void set(jsval val, JSContext* cx) {
if (val.isString()) {
string = val.toString();
if (!cx) {
cx = ScriptingCore::getInstance()->getGlobalContext();
}
buffer = JS_EncodeString(cx, string);
this->set(val.toString(), cx);
} else {
buffer = NULL;
}
@ -286,7 +283,14 @@ public:
if (!cx) {
cx = ScriptingCore::getInstance()->getGlobalContext();
}
buffer = JS_EncodeString(cx, string);
// Not suppored in SpiderMonkey v19
//buffer = JS_EncodeString(cx, string);
const jschar *chars = JS_GetStringCharsZ(cx, string);
size_t l = JS_GetStringLength(string);
char* pUTF8Str = cc_utf16_to_utf8((const unsigned short*)chars, l, NULL, NULL);
buffer = pUTF8Str;
}
std::string get() {
return buffer;

View File

@ -1 +1 @@
e0892eb5a623d56700e48e717dbc04c367b3b48a
e4b7d86461a17a555283bbc28cba2ab48cab21cd

@ -1 +1 @@
Subproject commit a4cf50ac9b5541a1ba948bb459fa5bf7b4917e65
Subproject commit 9918c2317e922dd8d866e4df09b039aba8d48134

View File

@ -1 +1 @@
9594a5677c70358b9e128381d6481eeed0e80723
f432fb0be7f47a71e1ceeb380fa604fab9e2ac31

View File

@ -258,12 +258,12 @@ void JSB_CCPhysicsDebugNode_createClass(JSContext *cx, JSObject* globalObj, cons
{0, 0, 0, 0, 0}
};
static JSFunctionSpec funcs[] = {
JS_FN("_setSpace", JSB_CCPhysicsDebugNode_setSpace_, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("getSpace", JSB_CCPhysicsDebugNode_space, 0, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("_setSpace", JSB_CCPhysicsDebugNode_setSpace_, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("getSpace", JSB_CCPhysicsDebugNode_space, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
static JSFunctionSpec st_funcs[] = {
JS_FN("_create", JSB_CCPhysicsDebugNode_debugNodeForCPSpace__static, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("_create", JSB_CCPhysicsDebugNode_debugNodeForCPSpace__static, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
@ -443,16 +443,16 @@ void JSPROXY_CCPhysicsSprite_createClass(JSContext *cx, JSObject* globalObj)
{0, 0, 0, 0, 0}
};
static JSFunctionSpec funcs[] = {
JS_FN("getCPBody", JSPROXY_CCPhysicsSprite_getCPBody, 0, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("getIgnoreBodyRotation", JSPROXY_CCPhysicsSprite_ignoreBodyRotation, 0, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("_setCPBody", JSPROXY_CCPhysicsSprite_setCPBody_, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("setIgnoreBodyRotation", JSPROXY_CCPhysicsSprite_setIgnoreBodyRotation_, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("getCPBody", JSPROXY_CCPhysicsSprite_getCPBody, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("getIgnoreBodyRotation", JSPROXY_CCPhysicsSprite_ignoreBodyRotation, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("_setCPBody", JSPROXY_CCPhysicsSprite_setCPBody_, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("setIgnoreBodyRotation", JSPROXY_CCPhysicsSprite_setIgnoreBodyRotation_, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
static JSFunctionSpec st_funcs[] = {
JS_FN("create", JSPROXY_CCPhysicsSprite_spriteWithFile_rect__static, 2, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("createWithSpriteFrame", JSPROXY_CCPhysicsSprite_spriteWithSpriteFrame__static, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("createWithSpriteFrameName", JSPROXY_CCPhysicsSprite_spriteWithSpriteFrameName__static, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("create", JSPROXY_CCPhysicsSprite_spriteWithFile_rect__static, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("createWithSpriteFrame", JSPROXY_CCPhysicsSprite_spriteWithSpriteFrame__static, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("createWithSpriteFrameName", JSPROXY_CCPhysicsSprite_spriteWithSpriteFrameName__static, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
@ -1528,8 +1528,8 @@ void JSB_cpBase_createClass(JSContext *cx, JSObject* globalObj, const char* name
{0, 0, 0, 0, 0}
};
static JSFunctionSpec funcs[] = {
JS_FN("getHandle", JSB_cpBase_getHandle, 0, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("setHandle", JSB_cpBase_setHandle, 1, JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE),
JS_FN("getHandle", JSB_cpBase_getHandle, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FN("setHandle", JSB_cpBase_setHandle, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
static JSFunctionSpec st_funcs[] = {

View File

@ -21,7 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "js_bindings_config.h"
#include "js_bindings_core.h"
@ -29,6 +28,7 @@
// cocos2d + chipmunk registration files
#include "js_bindings_chipmunk_registration.h"
#pragma mark - Hash
using namespace cocos2d;
@ -80,8 +80,12 @@ JSBool JSBCore_log(JSContext *cx, uint32_t argc, jsval *vp)
JSString *string = NULL;
JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &string);
if (string) {
char *cstr = JS_EncodeString(cx, string);
fprintf(stderr, "%s\n", cstr);
// Not supported in SpiderMonkey v19
//char *cstr = JS_EncodeString(cx, string);
const jschar *chars = JS_GetStringCharsZ(cx, string);
size_t l = JS_GetStringLength(string);
char* pUTF8Str = cc_utf16_to_utf8((const unsigned short*)chars, l, NULL, NULL);
CCLOG(pUTF8Str);
}
return JS_TRUE;

View File

@ -78,14 +78,12 @@ JSBool jsval_to_long( JSContext *cx, jsval vp, long *r )
JSBool jsval_to_longlong( JSContext *cx, jsval vp, long long *r )
{
JSObject *tmp_arg;
if( ! JS_ValueToObject( cx, vp, &tmp_arg ) )
return JS_FALSE;
JSBool ok = JS_ValueToObject( cx, vp, &tmp_arg );
JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error converting value to object");
JSB_PRECONDITION2( tmp_arg && JS_IsTypedArrayObject( tmp_arg ), cx, JS_FALSE, "Not a TypedArray object");
JSB_PRECONDITION2( JS_GetTypedArrayByteLength( tmp_arg ) == sizeof(long long), cx, JS_FALSE, "Invalid Typed Array length");
JSB_PRECONDITION( tmp_arg && JS_IsTypedArrayObject( tmp_arg, cx ), "Not a TypedArray object");
JSB_PRECONDITION( JS_GetTypedArrayByteLength( tmp_arg, cx ) == sizeof(long long), "Invalid Typed Array lenght");
int32_t* arg_array = (int32_t*)JS_GetArrayBufferViewData( tmp_arg, cx );
uint32_t* arg_array = (uint32_t*)JS_GetArrayBufferViewData( tmp_arg );
long long ret = arg_array[0];
ret = ret << 32;
ret |= arg_array[1];
@ -201,17 +199,16 @@ JSBool jsval_to_charptr( JSContext *cx, jsval vp, const char **ret )
// root it
vp = STRING_TO_JSVAL(jsstr);
char *ptr = JS_EncodeString(cx, jsstr);
JSB_PRECONDITION2(ptr, cx, JS_FALSE, "Error encoding string");
// Not supported in SpiderMonkey v19
//char *ptr = JS_EncodeString(cx, jsstr);
JSStringWrapper strWrapper(jsstr);
// XXX: It is converted to CCString and then back to char* to autorelease the created object.
CCString *tmp = CCString::create(ptr);
CCString *tmp = CCString::create(strWrapper.get());
JSB_PRECONDITION2( tmp, cx, JS_FALSE, "Error creating string from UTF8");
*ret = tmp->getCString();
JS_free( cx, ptr );
return JS_TRUE;
}

View File

@ -1,659 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsgc_barrier_h___
#define jsgc_barrier_h___
#include "jsapi.h"
#include "gc/Heap.h"
#include "gc/Root.h"
#include "js/HashTable.h"
/*
* A write barrier is a mechanism used by incremental or generation GCs to
* ensure that every value that needs to be marked is marked. In general, the
* write barrier should be invoked whenever a write can cause the set of things
* traced through by the GC to change. This includes:
* - writes to object properties
* - writes to array slots
* - writes to fields like JSObject::shape_ that we trace through
* - writes to fields in private data, like JSGenerator::obj
* - writes to non-markable fields like JSObject::private that point to
* markable data
* The last category is the trickiest. Even though the private pointers does not
* point to a GC thing, changing the private pointer may change the set of
* objects that are traced by the GC. Therefore it needs a write barrier.
*
* Every barriered write should have the following form:
* <pre-barrier>
* obj->field = value; // do the actual write
* <post-barrier>
* The pre-barrier is used for incremental GC and the post-barrier is for
* generational GC.
*
* PRE-BARRIER
*
* To understand the pre-barrier, let's consider how incremental GC works. The
* GC itself is divided into "slices". Between each slice, JS code is allowed to
* run. Each slice should be short so that the user doesn't notice the
* interruptions. In our GC, the structure of the slices is as follows:
*
* 1. ... JS work, which leads to a request to do GC ...
* 2. [first GC slice, which performs all root marking and possibly more marking]
* 3. ... more JS work is allowed to run ...
* 4. [GC mark slice, which runs entirely in drainMarkStack]
* 5. ... more JS work ...
* 6. [GC mark slice, which runs entirely in drainMarkStack]
* 7. ... more JS work ...
* 8. [GC marking finishes; sweeping done non-incrementally; GC is done]
* 9. ... JS continues uninterrupted now that GC is finishes ...
*
* Of course, there may be a different number of slices depending on how much
* marking is to be done.
*
* The danger inherent in this scheme is that the JS code in steps 3, 5, and 7
* might change the heap in a way that causes the GC to collect an object that
* is actually reachable. The write barrier prevents this from happening. We use
* a variant of incremental GC called "snapshot at the beginning." This approach
* guarantees the invariant that if an object is reachable in step 2, then we
* will mark it eventually. The name comes from the idea that we take a
* theoretical "snapshot" of all reachable objects in step 2; all objects in
* that snapshot should eventually be marked. (Note that the write barrier
* verifier code takes an actual snapshot.)
*
* The basic correctness invariant of a snapshot-at-the-beginning collector is
* that any object reachable at the end of the GC (step 9) must either:
* (1) have been reachable at the beginning (step 2) and thus in the snapshot
* (2) or must have been newly allocated, in steps 3, 5, or 7.
* To deal with case (2), any objects allocated during an incremental GC are
* automatically marked black.
*
* This strategy is actually somewhat conservative: if an object becomes
* unreachable between steps 2 and 8, it would be safe to collect it. We won't,
* mainly for simplicity. (Also, note that the snapshot is entirely
* theoretical. We don't actually do anything special in step 2 that we wouldn't
* do in a non-incremental GC.
*
* It's the pre-barrier's job to maintain the snapshot invariant. Consider the
* write "obj->field = value". Let the prior value of obj->field be
* value0. Since it's possible that value0 may have been what obj->field
* contained in step 2, when the snapshot was taken, the barrier marks
* value0. Note that it only does this if we're in the middle of an incremental
* GC. Since this is rare, the cost of the write barrier is usually just an
* extra branch.
*
* In practice, we implement the pre-barrier differently based on the type of
* value0. E.g., see JSObject::writeBarrierPre, which is used if obj->field is
* a JSObject*. It takes value0 as a parameter.
*
* POST-BARRIER
*
* These are not yet implemented. Once we get generational GC, they will allow
* us to keep track of pointers from non-nursery space into the nursery.
*
* IMPLEMENTATION DETAILS
*
* Since it would be awkward to change every write to memory into a function
* call, this file contains a bunch of C++ classes and templates that use
* operator overloading to take care of barriers automatically. In many cases,
* all that's necessary to make some field be barriered is to replace
* Type *field;
* with
* HeapPtr<Type> field;
* There are also special classes HeapValue and HeapId, which barrier js::Value
* and jsid, respectively.
*
* One additional note: not all object writes need to be barriered. Writes to
* newly allocated objects do not need a pre-barrier. In these cases, we use
* the "obj->field.init(value)" method instead of "obj->field = value". We use
* the init naming idiom in many places to signify that a field is being
* assigned for the first time.
*/
struct JSXML;
namespace js {
template<class T, typename Unioned = uintptr_t>
class EncapsulatedPtr
{
protected:
union {
T *value;
Unioned other;
};
public:
EncapsulatedPtr() : value(NULL) {}
EncapsulatedPtr(T *v) : value(v) {}
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
~EncapsulatedPtr() { pre(); }
/* Use to set the pointer to NULL. */
void clear() {
pre();
value = NULL;
}
EncapsulatedPtr<T, Unioned> &operator=(T *v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
return *this;
}
EncapsulatedPtr<T, Unioned> &operator=(const EncapsulatedPtr<T> &v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
value = v.value;
return *this;
}
/* Use this if the automatic coercion to T* isn't working. */
T *get() const { return value; }
/*
* Use these if you want to change the value without invoking the barrier.
* Obviously this is dangerous unless you know the barrier is not needed.
*/
T **unsafeGet() { return &value; }
void unsafeSet(T *v) { value = v; }
Unioned *unsafeGetUnioned() { return &other; }
T &operator*() const { return *value; }
T *operator->() const { return value; }
operator T*() const { return value; }
protected:
void pre();
};
template <class T, class Unioned = uintptr_t>
class HeapPtr : public EncapsulatedPtr<T, Unioned>
{
public:
HeapPtr() : EncapsulatedPtr<T>(NULL) {}
explicit HeapPtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
explicit HeapPtr(const HeapPtr<T> &v)
: EncapsulatedPtr<T>(v) { post(); }
void init(T *v) {
JS_ASSERT(!IsPoisonedPtr<T>(v));
this->value = v;
post();
}
HeapPtr<T, Unioned> &operator=(T *v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
this->value = v;
post();
return *this;
}
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
this->value = v.value;
post();
return *this;
}
protected:
void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
/* Make this friend so it can access pre() and post(). */
template<class T1, class T2>
friend inline void
BarrieredSetPair(JSCompartment *comp,
HeapPtr<T1> &v1, T1 *val1,
HeapPtr<T2> &v2, T2 *val2);
};
/*
* FixedHeapPtr is designed for one very narrow case: replacing immutable raw
* pointers to GC-managed things, implicitly converting to a handle type for
* ease of use. Pointers encapsulated by this type must:
*
* be immutable (no incremental write barriers),
* never point into the nursery (no generational write barriers), and
* be traced via MarkRuntime (we use fromMarkedLocation).
*
* In short: you *really* need to know what you're doing before you use this
* class!
*/
template <class T>
class FixedHeapPtr
{
T *value;
public:
operator T*() const { return value; }
T * operator->() const { return value; }
operator Handle<T*>() const {
return Handle<T*>::fromMarkedLocation(&value);
}
void init(T *ptr) {
value = ptr;
}
};
template <class T>
class RelocatablePtr : public EncapsulatedPtr<T>
{
public:
RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) {
if (v)
post();
}
explicit RelocatablePtr(const RelocatablePtr<T> &v) : EncapsulatedPtr<T>(v) {
if (this->value)
post();
}
~RelocatablePtr() {
if (this->value)
relocate(this->value->compartment());
}
RelocatablePtr<T> &operator=(T *v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
if (v) {
this->value = v;
post();
} else if (this->value) {
JSCompartment *comp = this->value->compartment();
this->value = v;
relocate(comp);
}
return *this;
}
RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
if (v.value) {
this->value = v.value;
post();
} else if (this->value) {
JSCompartment *comp = this->value->compartment();
this->value = v;
relocate(comp);
}
return *this;
}
protected:
inline void post();
inline void relocate(JSCompartment *comp);
};
/*
* This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
* barriers with only one branch to check if we're in an incremental GC.
*/
template<class T1, class T2>
static inline void
BarrieredSetPair(JSCompartment *comp,
HeapPtr<T1> &v1, T1 *val1,
HeapPtr<T2> &v2, T2 *val2)
{
if (T1::needWriteBarrierPre(comp)) {
v1.pre();
v2.pre();
}
v1.unsafeSet(val1);
v2.unsafeSet(val2);
v1.post();
v2.post();
}
struct Shape;
class BaseShape;
namespace types { struct TypeObject; }
typedef EncapsulatedPtr<JSObject> EncapsulatedPtrObject;
typedef EncapsulatedPtr<JSScript> EncapsulatedPtrScript;
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
typedef HeapPtr<JSObject> HeapPtrObject;
typedef HeapPtr<JSFunction> HeapPtrFunction;
typedef HeapPtr<JSString> HeapPtrString;
typedef HeapPtr<JSScript> HeapPtrScript;
typedef HeapPtr<Shape> HeapPtrShape;
typedef HeapPtr<BaseShape> HeapPtrBaseShape;
typedef HeapPtr<types::TypeObject> HeapPtrTypeObject;
typedef HeapPtr<JSXML> HeapPtrXML;
/* Useful for hashtables with a HeapPtr as key. */
template<class T>
struct HeapPtrHasher
{
typedef HeapPtr<T> Key;
typedef T *Lookup;
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
};
/* Specialized hashing policy for HeapPtrs. */
template <class T>
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
template<class T>
struct EncapsulatedPtrHasher
{
typedef EncapsulatedPtr<T> Key;
typedef T *Lookup;
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
};
template <class T>
struct DefaultHasher< EncapsulatedPtr<T> > : EncapsulatedPtrHasher<T> { };
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
{
protected:
Value value;
/*
* Ensure that EncapsulatedValue is not constructable, except by our
* implementations.
*/
EncapsulatedValue() MOZ_DELETE;
EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
EncapsulatedValue(const Value &v) : value(v) {}
~EncapsulatedValue() {}
public:
bool operator==(const EncapsulatedValue &v) const { return value == v.value; }
bool operator!=(const EncapsulatedValue &v) const { return value != v.value; }
const Value &get() const { return value; }
Value *unsafeGet() { return &value; }
operator const Value &() const { return value; }
JSGCTraceKind gcKind() const { return value.gcKind(); }
uint64_t asRawBits() const { return value.asRawBits(); }
static inline void writeBarrierPre(const Value &v);
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
protected:
inline void pre();
inline void pre(JSCompartment *comp);
private:
friend class ValueOperations<EncapsulatedValue>;
const Value * extract() const { return &value; }
};
class HeapValue : public EncapsulatedValue
{
public:
explicit inline HeapValue();
explicit inline HeapValue(const Value &v);
explicit inline HeapValue(const HeapValue &v);
inline ~HeapValue();
inline void init(const Value &v);
inline void init(JSCompartment *comp, const Value &v);
inline HeapValue &operator=(const Value &v);
inline HeapValue &operator=(const HeapValue &v);
/*
* This is a faster version of operator=. Normally, operator= has to
* determine the compartment of the value before it can decide whether to do
* the barrier. If you already know the compartment, it's faster to pass it
* in.
*/
inline void set(JSCompartment *comp, const Value &v);
static inline void writeBarrierPost(const Value &v, Value *addr);
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
private:
inline void post();
inline void post(JSCompartment *comp);
};
class RelocatableValue : public EncapsulatedValue
{
public:
explicit inline RelocatableValue();
explicit inline RelocatableValue(const Value &v);
inline RelocatableValue(const RelocatableValue &v);
inline ~RelocatableValue();
inline RelocatableValue &operator=(const Value &v);
inline RelocatableValue &operator=(const RelocatableValue &v);
private:
inline void post();
inline void post(JSCompartment *comp);
inline void relocate();
};
class HeapSlot : public EncapsulatedValue
{
/*
* Operator= is not valid for HeapSlot because is must take the object and
* slot offset to provide to the post/generational barrier.
*/
inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
public:
explicit inline HeapSlot() MOZ_DELETE;
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
inline ~HeapSlot();
inline void init(JSObject *owner, uint32_t slot, const Value &v);
inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
inline void set(JSObject *owner, uint32_t slot, const Value &v);
inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slot);
private:
inline void post(JSObject *owner, uint32_t slot);
inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
};
/*
* NOTE: This is a placeholder for bug 619558.
*
* Run a post write barrier that encompasses multiple contiguous slots in a
* single step.
*/
inline void
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count);
/*
* This is a post barrier for HashTables whose key can be moved during a GC.
*/
template <class Map, class Key>
inline void
HashTableWriteBarrierPost(JSCompartment *comp, const Map *map, const Key &key)
{
#ifdef JS_GCGENERATIONAL
if (key && comp->gcNursery.isInside(key))
comp->gcStoreBuffer.putGeneric(HashKeyRef(map, key));
#endif
}
static inline const Value *
Valueify(const EncapsulatedValue *array)
{
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
return (const Value *)array;
}
static inline HeapValue *
HeapValueify(Value *v)
{
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
return (HeapValue *)v;
}
class HeapSlotArray
{
HeapSlot *array;
public:
HeapSlotArray(HeapSlot *array) : array(array) {}
operator const Value *() const { return Valueify(array); }
operator HeapSlot *() const { return array; }
HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
};
class EncapsulatedId
{
protected:
jsid value;
private:
EncapsulatedId(const EncapsulatedId &v) MOZ_DELETE;
public:
explicit EncapsulatedId() : value(JSID_VOID) {}
explicit EncapsulatedId(jsid id) : value(id) {}
~EncapsulatedId();
inline EncapsulatedId &operator=(const EncapsulatedId &v);
bool operator==(jsid id) const { return value == id; }
bool operator!=(jsid id) const { return value != id; }
jsid get() const { return value; }
jsid *unsafeGet() { return &value; }
operator jsid() const { return value; }
protected:
inline void pre();
};
class RelocatableId : public EncapsulatedId
{
public:
explicit RelocatableId() : EncapsulatedId() {}
explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {}
inline ~RelocatableId();
inline RelocatableId &operator=(jsid id);
inline RelocatableId &operator=(const RelocatableId &v);
};
class HeapId : public EncapsulatedId
{
public:
explicit HeapId() : EncapsulatedId() {}
explicit inline HeapId(jsid id);
inline ~HeapId();
inline void init(jsid id);
inline HeapId &operator=(jsid id);
inline HeapId &operator=(const HeapId &v);
private:
inline void post();
HeapId(const HeapId &v) MOZ_DELETE;
};
/*
* Incremental GC requires that weak pointers have read barriers. This is mostly
* an issue for empty shapes stored in JSCompartment. The problem happens when,
* during an incremental GC, some JS code stores one of the compartment's empty
* shapes into an object already marked black. Normally, this would not be a
* problem, because the empty shape would have been part of the initial snapshot
* when the GC started. However, since this is a weak pointer, it isn't. So we
* may collect the empty shape even though a live object points to it. To fix
* this, we mark these empty shapes black whenever they get read out.
*/
template<class T>
class ReadBarriered
{
T *value;
public:
ReadBarriered() : value(NULL) {}
ReadBarriered(T *value) : value(value) {}
T *get() const {
if (!value)
return NULL;
T::readBarrier(value);
return value;
}
operator T*() const { return get(); }
T &operator*() const { return *get(); }
T *operator->() const { return get(); }
T **unsafeGet() { return &value; }
void set(T *v) { value = v; }
operator bool() { return !!value; }
};
class ReadBarrieredValue
{
Value value;
public:
ReadBarrieredValue() : value(UndefinedValue()) {}
ReadBarrieredValue(const Value &value) : value(value) {}
inline const Value &get() const;
Value *unsafeGet() { return &value; }
inline operator const Value &() const;
inline JSObject &toObject() const;
};
namespace tl {
template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
{ static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapSlot> { static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapId> { static const bool result = false; };
} /* namespace tl */
} /* namespace js */
#endif /* jsgc_barrier_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -77,8 +77,14 @@ class MutableHandleBase {};
namespace JS {
class AutoAssertNoGC;
template <typename T> class MutableHandle;
JS_FRIEND_API(void) EnterAssertNoGCScope();
JS_FRIEND_API(void) LeaveAssertNoGCScope();
JS_FRIEND_API(bool) InNoGCScope();
/*
* Handle provides an implicit constructor for NullPtr so that, given:
* foo(Handle<JSObject*> h);
@ -316,6 +322,169 @@ class InternalHandle<T*>
}
};
#ifdef DEBUG
template <typename T>
class IntermediateNoGC
{
T t_;
public:
IntermediateNoGC(const T &t) : t_(t) {
EnterAssertNoGCScope();
}
IntermediateNoGC(const IntermediateNoGC &) {
EnterAssertNoGCScope();
}
~IntermediateNoGC() {
LeaveAssertNoGCScope();
}
const T &operator->() { return t_; }
operator const T &() { return t_; }
};
#endif
/*
* Return<T> wraps GC things that are returned from accessor methods. The
* wrapper helps to ensure correct rooting of the returned pointer and safe
* access while unrooted.
*
* Example usage in a method declaration:
*
* class Foo {
* HeapPtrScript script_;
* ...
* public:
* Return<JSScript*> script() { return script_; }
* };
*
* Example usage of method (1):
*
* Foo foo(...);
* RootedScript script(cx, foo->script());
*
* Example usage of method (2):
*
* Foo foo(...);
* foo->script()->needsArgsObj();
*
* The purpose of this class is to assert eagerly on incorrect use of GC thing
* pointers. For example:
*
* RootedShape shape(cx, ...);
* shape->parent.init(js_NewGCThing<Shape*>(cx, ...));
*
* In this expression, C++ is allowed to order these calls as follows:
*
* Call Effect
* ---- ------
* 1) RootedShape::operator-> Stores shape::ptr_ to stack.
* 2) js_NewGCThing<Shape*> Triggers GC and compaction of shapes. This
* moves shape::ptr_ to a new location.
* 3) HeapPtrObject::init This call takes the relocated shape::ptr_
* as |this|, crashing or, worse, corrupting
* the program's state on the first access
* to a member variable.
*
* If Shape::parent were an accessor function returning a Return<Shape*>, this
* could not happen: Return ensures either immediate rooting or no GC within
* the same expression.
*/
template <typename T>
class Return
{
friend class Rooted<T>;
const T ptr_;
public:
template <typename S>
Return(const S &ptr,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
: ptr_(ptr)
{}
Return(NullPtr) : ptr_(NULL) {}
/*
* |get(AutoAssertNoGC &)| is the safest way to access a Return<T> without
* rooting it first: it is impossible to call this method without an
* AutoAssertNoGC in scope, so the compiler will automatically catch any
* incorrect usage.
*
* Example:
* AutoAssertNoGC nogc;
* RawScript script = fun->script().get(nogc);
*/
const T &get(AutoAssertNoGC &) const {
return ptr_;
}
/*
* |operator->|'s result cannot be stored in a local variable, so it is safe
* to use in a CanGC context iff no GC can occur anywhere within the same
* expression (generally from one |;| to the next). |operator->| uses a
* temporary object as a guard and will assert if a CanGC context is
* encountered before the next C++ Sequence Point.
*
* INCORRECT:
* fun->script()->bindings = myBindings->clone(cx, ...);
*
* The compiler is allowed to reorder |fun->script()::operator->()| above
* the call to |clone(cx, ...)|. In this case, the RawScript C++ stores on
* the stack may be corrupted by a GC under |clone|. The subsequent
* dereference of this pointer to get |bindings| will result in an invalid
* access. This wrapper ensures that such usage asserts in DEBUG builds when
* it encounters this situation. Without this assertion, it is possible for
* such access to corrupt program state instead of crashing immediately.
*
* CORRECT:
* RootedScript clone(cx, myBindings->clone(cx, ...));
* fun->script()->bindings = clone;
*/
#ifdef DEBUG
IntermediateNoGC<T> operator->() const {
return IntermediateNoGC<T>(ptr_);
}
#else
const T &operator->() const {
return ptr_;
}
#endif
/*
* |unsafeGet()| is unsafe for most uses. Although it performs similar
* checking to |operator->|, its result can be stored to a local variable.
* For this reason, it should only be used when it would be incorrect or
* absurd to create a new Rooted for its use: e.g. for assertions.
*/
#ifdef DEBUG
IntermediateNoGC<T> unsafeGet() const {
return IntermediateNoGC<T>(ptr_);
}
#else
const T &unsafeGet() const {
return ptr_;
}
#endif
/*
* |operator==| is safe to use in any context. It is present to allow:
* JS_ASSERT(myScript == fun->script().unsafeGet());
*
* To be rewritten as:
* JS_ASSERT(fun->script() == myScript);
*
* Note: the new order tells C++ to use |Return<JSScript*>::operator=|
* instead of direct pointer comparison.
*/
bool operator==(const T &other) { return ptr_ == other; }
bool operator!=(const T &other) { return ptr_ != other; }
bool operator==(const Return<T> &other) { return ptr_ == other.ptr_; }
bool operator==(const JS::Handle<T> &other) { return ptr_ == other.get(); }
inline bool operator==(const Rooted<T> &other);
};
/*
* By default, pointers should use the inheritance hierarchy to find their
* ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
@ -332,12 +501,6 @@ struct RootMethods<T *>
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
};
#if !(defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING))
// Defined in vm/String.h.
template <>
class Rooted<JSStableString *>;
#endif
template <typename T>
class RootedBase {};
@ -356,27 +519,23 @@ class Rooted : public RootedBase<T>
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ContextFriendFields *cx = ContextFriendFields::get(cxArg);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
commonInit(cx->thingGCRooters);
#endif
}
void init(JSRuntime *rtArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
RuntimeFriendFields *rt = const_cast<RuntimeFriendFields *>(RuntimeFriendFields::get(rtArg));
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::getMainThread(rtArg);
commonInit(pt->thingGCRooters);
#endif
}
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&rt->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
void init(js::PerThreadData *ptArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::get(ptArg);
commonInit(pt->thingGCRooters);
#endif
}
@ -413,6 +572,40 @@ class Rooted : public RootedBase<T>
init(cx);
}
Rooted(js::PerThreadData *pt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(RootMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
Rooted(js::PerThreadData *pt, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
template <typename S>
Rooted(JSContext *cx, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial.ptr_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
}
template <typename S>
Rooted(js::PerThreadData *pt, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial.ptr_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
~Rooted()
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
@ -445,7 +638,25 @@ class Rooted : public RootedBase<T>
return ptr;
}
template <typename S>
T & operator =(const Return<S> &value)
{
ptr = value.ptr_;
return ptr;
}
private:
void commonInit(Rooted<void*> **thingGCRooters) {
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
#endif
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
Rooted<T> **stack, *prev;
#endif
@ -455,6 +666,19 @@ class Rooted : public RootedBase<T>
Rooted(const Rooted &) MOZ_DELETE;
};
#if !(defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING))
// Defined in vm/String.h.
template <>
class Rooted<JSStableString *>;
#endif
template <typename T>
bool
Return<T>::operator==(const Rooted<T> &other)
{
return ptr_ == other.get();
}
typedef Rooted<JSObject*> RootedObject;
typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSScript*> RootedScript;
@ -550,10 +774,6 @@ MutableHandle<T>::MutableHandle(js::Rooted<S> *root,
ptr = root->address();
}
JS_FRIEND_API(void) EnterAssertNoGCScope();
JS_FRIEND_API(void) LeaveAssertNoGCScope();
JS_FRIEND_API(bool) InNoGCScope();
/*
* The scoped guard object AutoAssertNoGC forces the GC to assert if a GC is
* attempted while the guard object is live. If you have a GC-unsafe operation
@ -581,15 +801,11 @@ public:
/*
* AssertCanGC will assert if it is called inside of an AutoAssertNoGC region.
*/
#ifdef DEBUG
JS_ALWAYS_INLINE void
AssertCanGC()
{
JS_ASSERT(!InNoGCScope());
}
#else
# define AssertCanGC()
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
extern void

View File

@ -1,193 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsgc_statistics_h___
#define jsgc_statistics_h___
#include <string.h>
#include "jsfriendapi.h"
#include "jspubtd.h"
#include "jsutil.h"
struct JSCompartment;
namespace js {
namespace gcstats {
enum Phase {
PHASE_GC_BEGIN,
PHASE_WAIT_BACKGROUND_THREAD,
PHASE_PURGE,
PHASE_MARK,
PHASE_MARK_DISCARD_CODE,
PHASE_MARK_ROOTS,
PHASE_MARK_TYPES,
PHASE_MARK_DELAYED,
PHASE_MARK_WEAK,
PHASE_MARK_GRAY,
PHASE_MARK_GRAY_WEAK,
PHASE_FINALIZE_START,
PHASE_SWEEP,
PHASE_SWEEP_ATOMS,
PHASE_SWEEP_COMPARTMENTS,
PHASE_SWEEP_TABLES,
PHASE_SWEEP_OBJECT,
PHASE_SWEEP_STRING,
PHASE_SWEEP_SCRIPT,
PHASE_SWEEP_SHAPE,
PHASE_SWEEP_IONCODE,
PHASE_SWEEP_DISCARD_CODE,
PHASE_DISCARD_ANALYSIS,
PHASE_DISCARD_TI,
PHASE_FREE_TI_ARENA,
PHASE_SWEEP_TYPES,
PHASE_CLEAR_SCRIPT_ANALYSIS,
PHASE_FINALIZE_END,
PHASE_DESTROY,
PHASE_GC_END,
PHASE_LIMIT
};
enum Stat {
STAT_NEW_CHUNK,
STAT_DESTROY_CHUNK,
STAT_LIMIT
};
class StatisticsSerializer;
struct Statistics {
Statistics(JSRuntime *rt);
~Statistics();
void beginPhase(Phase phase);
void endPhase(Phase phase);
void beginSlice(int collectedCount, int compartmentCount, gcreason::Reason reason);
void endSlice();
void reset(const char *reason) { slices.back().resetReason = reason; }
void nonincremental(const char *reason) { nonincrementalReason = reason; }
void count(Stat s) {
JS_ASSERT(s < STAT_LIMIT);
counts[s]++;
}
int64_t beginSCC();
void endSCC(unsigned scc, int64_t start);
jschar *formatMessage();
jschar *formatJSON(uint64_t timestamp);
private:
JSRuntime *runtime;
int64_t startupTime;
FILE *fp;
bool fullFormat;
/*
* GCs can't really nest, but a second GC can be triggered from within the
* JSGC_END callback.
*/
int gcDepth;
int collectedCount;
int compartmentCount;
const char *nonincrementalReason;
struct SliceData {
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
{
PodArrayZero(phaseTimes);
}
gcreason::Reason reason;
const char *resetReason;
int64_t start, end;
size_t startFaults, endFaults;
int64_t phaseTimes[PHASE_LIMIT];
int64_t duration() const { return end - start; }
};
Vector<SliceData, 8, SystemAllocPolicy> slices;
/* Most recent time when the given phase started. */
int64_t phaseStartTimes[PHASE_LIMIT];
/* Total time in a given phase for this GC. */
int64_t phaseTimes[PHASE_LIMIT];
/* Total time in a given phase over all GCs. */
int64_t phaseTotals[PHASE_LIMIT];
/* Number of events of this type for this GC. */
unsigned int counts[STAT_LIMIT];
/* Allocated space before the GC started. */
size_t preBytes;
/* Sweep times for SCCs of compartments. */
Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
void beginGC();
void endGC();
void gcDuration(int64_t *total, int64_t *maxPause);
void sccDurations(int64_t *total, int64_t *maxPause);
void printStats();
bool formatData(StatisticsSerializer &ss, uint64_t timestamp);
double computeMMU(int64_t resolution);
};
struct AutoGCSlice {
AutoGCSlice(Statistics &stats, int collectedCount, int compartmentCount, gcreason::Reason reason
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
stats.beginSlice(collectedCount, compartmentCount, reason);
}
~AutoGCSlice() { stats.endSlice(); }
Statistics &stats;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoPhase {
AutoPhase(Statistics &stats, Phase phase JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats), phase(phase) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginPhase(phase); }
~AutoPhase() { stats.endPhase(phase); }
Statistics &stats;
Phase phase;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoSCC {
AutoSCC(Statistics &stats, unsigned scc JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats), scc(scc) { JS_GUARD_OBJECT_NOTIFIER_INIT; start = stats.beginSCC(); }
~AutoSCC() { stats.endSCC(scc, start); }
Statistics &stats;
unsigned scc;
int64_t start;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
} /* namespace gcstats */
} /* namespace js */
#endif /* jsgc_statistics_h___ */

View File

@ -1,398 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef JSGC_GENERATIONAL
#ifndef jsgc_storebuffer_h___
#define jsgc_storebuffer_h___
#include "jsgc.h"
#include "jsalloc.h"
#include "gc/Marking.h"
namespace js {
namespace gc {
/*
* Note: this is a stub Nursery that does not actually contain a heap, just a
* set of pointers which are "inside" the nursery to implement verification.
*/
class Nursery
{
HashSet<void*, PointerHasher<void*, 3>, SystemAllocPolicy> nursery;
public:
Nursery() : nursery() {}
bool enable() {
if (!nursery.initialized())
return nursery.init();
return true;
}
void disable() {
if (!nursery.initialized())
return;
nursery.finish();
}
bool isInside(void *cell) const {
JS_ASSERT((uintptr_t(cell) & 0x3) == 0);
return nursery.initialized() && nursery.has(cell);
}
void insertPointer(void *cell) {
nursery.putNew(cell);
}
};
/*
* BufferableRef represents an abstract reference for use in the generational
* GC's remembered set. Entries in the store buffer that cannot be represented
* with the simple pointer-to-a-pointer scheme must derive from this class and
* use the generic store buffer interface.
*/
class BufferableRef
{
public:
virtual bool match(void *location) = 0;
virtual void mark(JSTracer *trc) = 0;
};
/*
* HashKeyRef represents a reference to a HashTable key. Manual HashTable
* barriers should should instantiate this template with their own table/key
* type to insert into the generic buffer with putGeneric.
*/
template <typename Map, typename Key>
class HashKeyRef : public BufferableRef
{
Map *map;
Key key;
typedef typename Map::Ptr Ptr;
public:
HashKeyRef(Map *m, const Key &k) : map(m), key(k) {}
bool match(void *location) {
Ptr p = map->lookup(key);
if (!p)
return false;
return &p->key == location;
}
void mark(JSTracer *trc) {}
};
/*
* The StoreBuffer observes all writes that occur in the system and performs
* efficient filtering of them to derive a remembered set for nursery GC.
*/
class StoreBuffer
{
/* TODO: profile to find the ideal size for these. */
static const size_t ValueBufferSize = 1 * 1024 * sizeof(Value *);
static const size_t CellBufferSize = 2 * 1024 * sizeof(Cell **);
static const size_t SlotBufferSize = 2 * 1024 * (sizeof(JSObject *) + sizeof(uint32_t));
static const size_t RelocValueBufferSize = 1 * 1024 * sizeof(Value *);
static const size_t RelocCellBufferSize = 1 * 1024 * sizeof(Cell **);
static const size_t GenericBufferSize = 1 * 1024 * sizeof(int);
static const size_t TotalSize = ValueBufferSize + CellBufferSize +
SlotBufferSize + RelocValueBufferSize + RelocCellBufferSize +
GenericBufferSize;
typedef HashSet<void *, PointerHasher<void *, 3>, SystemAllocPolicy> EdgeSet;
/*
* This buffer holds only a single type of edge. Using this buffer is more
* efficient than the generic buffer when many writes will be to the same
* type of edge: e.g. Value or Cell*.
*/
template<typename T>
class MonoTypeBuffer
{
friend class StoreBuffer;
StoreBuffer *owner;
Nursery *nursery;
T *base; /* Pointer to the start of the buffer. */
T *pos; /* Pointer to the current insertion position. */
T *top; /* Pointer to one element after the end. */
MonoTypeBuffer(StoreBuffer *owner, Nursery *nursery)
: owner(owner), nursery(nursery), base(NULL), pos(NULL), top(NULL)
{}
MonoTypeBuffer &operator=(const MonoTypeBuffer& other) MOZ_DELETE;
bool enable(uint8_t *region, size_t len);
void disable();
bool isEmpty() const { return pos == base; }
bool isFull() const { JS_ASSERT(pos <= top); return pos == top; }
/* Compaction algorithms. */
void compactNotInSet();
/*
* Attempts to reduce the usage of the buffer by removing unnecessary
* entries.
*/
virtual void compact();
/* Add one item to the buffer. */
void put(const T &v);
/* For verification. */
bool accumulateEdges(EdgeSet &edges);
};
/*
* Overrides the MonoTypeBuffer to support pointers that may be moved in
* memory outside of the GC's control.
*/
template <typename T>
class RelocatableMonoTypeBuffer : public MonoTypeBuffer<T>
{
friend class StoreBuffer;
RelocatableMonoTypeBuffer(StoreBuffer *owner, Nursery *nursery)
: MonoTypeBuffer<T>(owner, nursery)
{}
/* Override compaction to filter out removed items. */
void compactMoved();
virtual void compact();
/* Record a removal from the buffer. */
void unput(const T &v);
};
class GenericBuffer
{
friend class StoreBuffer;
StoreBuffer *owner;
Nursery *nursery;
uint8_t *base; /* Pointer to start of buffer. */
uint8_t *pos; /* Pointer to current buffer position. */
uint8_t *top; /* Pointer to one past the last entry. */
GenericBuffer(StoreBuffer *owner, Nursery *nursery)
: owner(owner), nursery(nursery)
{}
GenericBuffer &operator=(const GenericBuffer& other) MOZ_DELETE;
bool enable(uint8_t *region, size_t len);
void disable();
/* Check if a pointer is present in the buffer. */
bool containsEdge(void *location) const;
template <typename T>
void put(const T &t) {
/* Check if we have been enabled. */
if (!pos)
return;
/* Check for overflow. */
if (top - pos < (unsigned)(sizeof(unsigned) + sizeof(T))) {
owner->setOverflowed();
return;
}
*((unsigned *)pos) = sizeof(T);
pos += sizeof(unsigned);
T *p = (T *)pos;
new (p) T(t);
pos += sizeof(T);
}
};
class CellPtrEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<CellPtrEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<CellPtrEdge>;
Cell **edge;
CellPtrEdge(Cell **v) : edge(v) {}
bool operator==(const CellPtrEdge &other) const { return edge == other.edge; }
bool operator!=(const CellPtrEdge &other) const { return edge != other.edge; }
void *location() const { return (void *)edge; }
bool inRememberedSet(Nursery *n) {
return !n->isInside(edge) && n->isInside(*edge);
}
bool isNullEdge() const {
return !*edge;
}
CellPtrEdge tagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) | 1)); }
CellPtrEdge untagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) & ~1)); }
bool isTagged() const { return bool(uintptr_t(edge) & 1); }
};
class ValueEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<ValueEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<ValueEdge>;
Value *edge;
ValueEdge(Value *v) : edge(v) {}
bool operator==(const ValueEdge &other) const { return edge == other.edge; }
bool operator!=(const ValueEdge &other) const { return edge != other.edge; }
void *deref() const { return edge->isGCThing() ? edge->toGCThing() : NULL; }
void *location() const { return (void *)edge; }
bool inRememberedSet(Nursery *n) {
return !n->isInside(edge) && n->isInside(deref());
}
bool isNullEdge() const {
return !deref();
}
ValueEdge tagged() const { return ValueEdge((Value *)(uintptr_t(edge) | 1)); }
ValueEdge untagged() const { return ValueEdge((Value *)(uintptr_t(edge) & ~1)); }
bool isTagged() const { return bool(uintptr_t(edge) & 1); }
};
struct SlotEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<SlotEdge>;
JSObject *object;
uint32_t offset;
SlotEdge(JSObject *object, uint32_t offset) : object(object), offset(offset) {}
bool operator==(const SlotEdge &other) const {
return object == other.object && offset == other.offset;
}
bool operator!=(const SlotEdge &other) const {
return object != other.object || offset != other.offset;
}
HeapSlot *slotLocation() const {
if (object->isDenseArray()) {
if (offset >= object->getDenseArrayInitializedLength())
return NULL;
return (HeapSlot *)&object->getDenseArrayElement(offset);
}
if (offset >= object->slotSpan())
return NULL;
return &object->getSlotRef(offset);
}
void *deref() const {
HeapSlot *loc = slotLocation();
return (loc && loc->isGCThing()) ? loc->toGCThing() : NULL;
}
void *location() const {
return (void *)slotLocation();
}
bool inRememberedSet(Nursery *n) {
return !n->isInside(object) && n->isInside(deref());
}
bool isNullEdge() const {
return !deref();
}
};
MonoTypeBuffer<ValueEdge> bufferVal;
MonoTypeBuffer<CellPtrEdge> bufferCell;
MonoTypeBuffer<SlotEdge> bufferSlot;
RelocatableMonoTypeBuffer<ValueEdge> bufferRelocVal;
RelocatableMonoTypeBuffer<CellPtrEdge> bufferRelocCell;
GenericBuffer bufferGeneric;
Nursery *nursery;
void *buffer;
bool overflowed;
bool enabled;
/* For the verifier. */
EdgeSet edgeSet;
/* For use by our owned buffers. */
void setOverflowed() { overflowed = true; }
public:
StoreBuffer(Nursery *n)
: bufferVal(this, n), bufferCell(this, n), bufferSlot(this, n),
bufferRelocVal(this, n), bufferRelocCell(this, n), bufferGeneric(this, n),
nursery(n), buffer(NULL), overflowed(false), enabled(false)
{}
bool enable();
void disable();
bool isEnabled() { return enabled; }
/* Get the overflowed status. */
bool hasOverflowed() const { return overflowed; }
/* Insert a single edge into the buffer/remembered set. */
void putValue(Value *v) {
bufferVal.put(v);
}
void putCell(Cell **o) {
bufferCell.put(o);
}
void putSlot(JSObject *obj, uint32_t slot) {
bufferSlot.put(SlotEdge(obj, slot));
}
/* Insert or update a single edge in the Relocatable buffer. */
void putRelocatableValue(Value *v) {
bufferRelocVal.put(v);
}
void putRelocatableCell(Cell **c) {
bufferRelocCell.put(c);
}
void removeRelocatableValue(Value *v) {
bufferRelocVal.unput(v);
}
void removeRelocatableCell(Cell **c) {
bufferRelocCell.unput(c);
}
/* Insert an entry into the generic buffer. */
template <typename T>
void putGeneric(const T &t) {
bufferGeneric.put(t);
}
/* For the verifier. */
bool coalesceForVerification();
void releaseVerificationData();
bool containsEdgeAt(void *loc) const;
};
} /* namespace gc */
} /* namespace js */
#endif /* jsgc_storebuffer_h___ */
#endif /* JSGC_GENERATIONAL */

View File

@ -20,7 +20,7 @@
/* Define to 1 if SpiderMonkey should support the ability to perform
entirely too much GC. */
#define JS_GC_ZEAL 1
/* #undef JS_GC_ZEAL */
/* Define to 1 if the <endian.h> header is present and
useable. See jscpucfg.h. */

View File

@ -375,3 +375,5 @@ MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 321, 0, JSEXN_TYPEERR, "proxy must report
MSG_DEF(JSMSG_CANT_SET_NW_NC, 322, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 323, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 324, 2, JSEXN_TYPEERR, "{0} does not refer to {1}")
MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 325, 2, JSEXN_TYPEERR, "{0} is a wrapper around {1}, but a direct reference is required")
MSG_DEF(JSMSG_UNWRAP_DENIED, 326, 0, JSEXN_ERR, "permission denied to unwrap object")

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_heap_api_h___
#define js_heap_api_h___
/* These values are private to the JS engine. */
namespace js {
namespace gc {
/*
* Page size must be static to support our arena pointer optimizations, so we
* are forced to support each platform with non-4096 pages as a special case.
* Note: The freelist supports a maximum arena shift of 15.
* Note: Do not use JS_CPU_SPARC here, this header is used outside JS.
*/
#if (defined(SOLARIS) || defined(__FreeBSD__)) && \
(defined(__sparc) || defined(__sparcv9) || defined(__ia64))
const size_t PageShift = 13;
const size_t ArenaShift = PageShift;
#elif defined(__powerpc64__)
const size_t PageShift = 16;
const size_t ArenaShift = 12;
#else
const size_t PageShift = 12;
const size_t ArenaShift = PageShift;
#endif
const size_t PageSize = size_t(1) << PageShift;
const size_t ArenaSize = size_t(1) << ArenaShift;
const size_t ArenaMask = ArenaSize - 1;
const size_t ChunkShift = 20;
const size_t ChunkSize = size_t(1) << ChunkShift;
const size_t ChunkMask = ChunkSize - 1;
} /* namespace gc */
} /* namespace js */
namespace JS {
namespace shadow {
struct ArenaHeader
{
JSCompartment *compartment;
};
} /* namespace shadow */
static inline shadow::ArenaHeader *
GetGCThingArena(void *thing)
{
uintptr_t addr = uintptr_t(thing);
addr &= ~js::gc::ArenaMask;
return reinterpret_cast<shadow::ArenaHeader *>(addr);
}
static inline JSCompartment *
GetGCThingCompartment(void *thing)
{
JS_ASSERT(thing);
return GetGCThingArena(thing)->compartment;
}
static inline JSCompartment *
GetObjectCompartment(JSObject *obj)
{
return GetGCThingCompartment(obj);
}
} /* namespace JS */
#endif /* js_heap_api_h___ */

View File

@ -38,22 +38,37 @@ namespace JS {
struct TypeInferenceSizes
{
TypeInferenceSizes()
: scripts(0)
, objects(0)
, tables(0)
, temporary(0)
: typeScripts(0)
, typeResults(0)
, analysisPool(0)
, typePool(0)
, pendingArrays(0)
, allocationSiteTables(0)
, arrayTypeTables(0)
, objectTypeTables(0)
, typeObjects(0)
{}
size_t scripts;
size_t objects;
size_t tables;
size_t temporary;
size_t typeScripts;
size_t typeResults;
size_t analysisPool;
size_t typePool;
size_t pendingArrays;
size_t allocationSiteTables;
size_t arrayTypeTables;
size_t objectTypeTables;
size_t typeObjects;
void add(TypeInferenceSizes &sizes) {
this->scripts += sizes.scripts;
this->objects += sizes.objects;
this->tables += sizes.tables;
this->temporary += sizes.temporary;
this->typeScripts += sizes.typeScripts;
this->typeResults += sizes.typeResults;
this->analysisPool += sizes.analysisPool;
this->typePool += sizes.typePool;
this->pendingArrays += sizes.pendingArrays;
this->allocationSiteTables += sizes.allocationSiteTables;
this->arrayTypeTables += sizes.arrayTypeTables;
this->objectTypeTables += sizes.objectTypeTables;
this->typeObjects += sizes.typeObjects;
}
};
@ -129,10 +144,15 @@ struct CompartmentStats
, extra2(0)
, gcHeapArenaAdmin(0)
, gcHeapUnusedGcThings(0)
, gcHeapObjectsNonFunction(0)
, gcHeapObjectsOrdinary(0)
, gcHeapObjectsFunction(0)
, gcHeapStrings(0)
, gcHeapShapesTree(0)
, gcHeapObjectsDenseArray(0)
, gcHeapObjectsSlowArray(0)
, gcHeapObjectsCrossCompartmentWrapper(0)
, gcHeapStringsNormal(0)
, gcHeapStringsShort(0)
, gcHeapShapesTreeGlobalParented(0)
, gcHeapShapesTreeNonGlobalParented(0)
, gcHeapShapesDict(0)
, gcHeapShapesBase(0)
, gcHeapScripts(0)
@ -147,7 +167,7 @@ struct CompartmentStats
, objectsExtraRegExpStatics(0)
, objectsExtraPropertyIteratorData(0)
, objectsExtraPrivate(0)
, nonHugeStringChars(0)
, stringCharsNonHuge(0)
, shapesExtraTreeTables(0)
, shapesExtraDictTables(0)
, shapesExtraTreeShapeKids(0)
@ -156,7 +176,7 @@ struct CompartmentStats
, jaegerData(0)
, ionData(0)
, compartmentObject(0)
, crossCompartmentWrappers(0)
, crossCompartmentWrappersTable(0)
, regexpCompartment(0)
, debuggeesSet(0)
{}
@ -166,10 +186,15 @@ struct CompartmentStats
, extra2(other.extra2)
, gcHeapArenaAdmin(other.gcHeapArenaAdmin)
, gcHeapUnusedGcThings(other.gcHeapUnusedGcThings)
, gcHeapObjectsNonFunction(other.gcHeapObjectsNonFunction)
, gcHeapObjectsOrdinary(other.gcHeapObjectsOrdinary)
, gcHeapObjectsFunction(other.gcHeapObjectsFunction)
, gcHeapStrings(other.gcHeapStrings)
, gcHeapShapesTree(other.gcHeapShapesTree)
, gcHeapObjectsDenseArray(other.gcHeapObjectsDenseArray)
, gcHeapObjectsSlowArray(other.gcHeapObjectsSlowArray)
, gcHeapObjectsCrossCompartmentWrapper(other.gcHeapObjectsCrossCompartmentWrapper)
, gcHeapStringsNormal(other.gcHeapStringsNormal)
, gcHeapStringsShort(other.gcHeapStringsShort)
, gcHeapShapesTreeGlobalParented(other.gcHeapShapesTreeGlobalParented)
, gcHeapShapesTreeNonGlobalParented(other.gcHeapShapesTreeNonGlobalParented)
, gcHeapShapesDict(other.gcHeapShapesDict)
, gcHeapShapesBase(other.gcHeapShapesBase)
, gcHeapScripts(other.gcHeapScripts)
@ -184,7 +209,7 @@ struct CompartmentStats
, objectsExtraRegExpStatics(other.objectsExtraRegExpStatics)
, objectsExtraPropertyIteratorData(other.objectsExtraPropertyIteratorData)
, objectsExtraPrivate(other.objectsExtraPrivate)
, nonHugeStringChars(other.nonHugeStringChars)
, stringCharsNonHuge(other.stringCharsNonHuge)
, shapesExtraTreeTables(other.shapesExtraTreeTables)
, shapesExtraDictTables(other.shapesExtraDictTables)
, shapesExtraTreeShapeKids(other.shapesExtraTreeShapeKids)
@ -193,7 +218,7 @@ struct CompartmentStats
, jaegerData(other.jaegerData)
, ionData(other.ionData)
, compartmentObject(other.compartmentObject)
, crossCompartmentWrappers(other.crossCompartmentWrappers)
, crossCompartmentWrappersTable(other.crossCompartmentWrappersTable)
, regexpCompartment(other.regexpCompartment)
, debuggeesSet(other.debuggeesSet)
, typeInferenceSizes(other.typeInferenceSizes)
@ -210,10 +235,15 @@ struct CompartmentStats
size_t gcHeapArenaAdmin;
size_t gcHeapUnusedGcThings;
size_t gcHeapObjectsNonFunction;
size_t gcHeapObjectsOrdinary;
size_t gcHeapObjectsFunction;
size_t gcHeapStrings;
size_t gcHeapShapesTree;
size_t gcHeapObjectsDenseArray;
size_t gcHeapObjectsSlowArray;
size_t gcHeapObjectsCrossCompartmentWrapper;
size_t gcHeapStringsNormal;
size_t gcHeapStringsShort;
size_t gcHeapShapesTreeGlobalParented;
size_t gcHeapShapesTreeNonGlobalParented;
size_t gcHeapShapesDict;
size_t gcHeapShapesBase;
size_t gcHeapScripts;
@ -229,7 +259,7 @@ struct CompartmentStats
size_t objectsExtraRegExpStatics;
size_t objectsExtraPropertyIteratorData;
size_t objectsExtraPrivate;
size_t nonHugeStringChars;
size_t stringCharsNonHuge;
size_t shapesExtraTreeTables;
size_t shapesExtraDictTables;
size_t shapesExtraTreeShapeKids;
@ -238,7 +268,7 @@ struct CompartmentStats
size_t jaegerData;
size_t ionData;
size_t compartmentObject;
size_t crossCompartmentWrappers;
size_t crossCompartmentWrappersTable;
size_t regexpCompartment;
size_t debuggeesSet;
@ -253,10 +283,15 @@ struct CompartmentStats
ADD(gcHeapArenaAdmin);
ADD(gcHeapUnusedGcThings);
ADD(gcHeapObjectsNonFunction);
ADD(gcHeapObjectsOrdinary);
ADD(gcHeapObjectsFunction);
ADD(gcHeapStrings);
ADD(gcHeapShapesTree);
ADD(gcHeapObjectsDenseArray);
ADD(gcHeapObjectsSlowArray);
ADD(gcHeapObjectsCrossCompartmentWrapper);
ADD(gcHeapStringsNormal);
ADD(gcHeapStringsShort);
ADD(gcHeapShapesTreeGlobalParented);
ADD(gcHeapShapesTreeNonGlobalParented);
ADD(gcHeapShapesDict);
ADD(gcHeapShapesBase);
ADD(gcHeapScripts);
@ -272,7 +307,7 @@ struct CompartmentStats
ADD(objectsExtraRegExpStatics);
ADD(objectsExtraPropertyIteratorData);
ADD(objectsExtraPrivate);
ADD(nonHugeStringChars);
ADD(stringCharsNonHuge);
ADD(shapesExtraTreeTables);
ADD(shapesExtraDictTables);
ADD(shapesExtraTreeShapeKids);
@ -281,7 +316,7 @@ struct CompartmentStats
ADD(jaegerData);
ADD(ionData);
ADD(compartmentObject);
ADD(crossCompartmentWrappers);
ADD(crossCompartmentWrappersTable);
ADD(regexpCompartment);
ADD(debuggeesSet);

View File

@ -21,7 +21,6 @@
#include "jstypes.h"
#ifdef __cplusplus
# include "js/TemplateLib.h"
# include "mozilla/Scoped.h"
@ -36,12 +35,8 @@ namespace js {
/* The private namespace is a superset of the public/shared namespaces. */
using namespace JS;
using namespace mozilla;
} /* namespace js */
#endif /* __cplusplus */
JS_BEGIN_EXTERN_C
/*
* Pattern used to overwrite freed memory. If you are accessing an object with
@ -171,6 +166,8 @@ static JS_INLINE void js_free(void* p)
}
#endif/* JS_USE_CUSTOM_ALLOCATOR */
JS_BEGIN_EXTERN_C
/*
* Replace bit-scanning code sequences with CPU-specific instructions to
* speedup calculations of ceiling/floor log2.
@ -330,6 +327,8 @@ JS_PUBLIC_API(size_t) js_FloorLog2wImpl(size_t n);
# error "NOT SUPPORTED"
#endif
JS_END_EXTERN_C
/*
* Internal function.
* Compute the log of the least power of 2 greater than or equal to n. This is
@ -371,9 +370,6 @@ JS_FLOOR_LOG2W(size_t n)
#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
#include <new>
/*
@ -903,8 +899,6 @@ inline bool IsPoisonedPtr(T *v)
}
#endif /* defined(__cplusplus) */
/*
* This is SpiderMonkey's equivalent to |nsMallocSizeOfFun|.
*/

View File

@ -242,7 +242,7 @@ class Vector : private AllocPolicy
size_t mReserved; /* Max elements of reserved or used space in this vector. */
#endif
AlignedStorage<sInlineBytes> storage;
mozilla::AlignedStorage<sInlineBytes> storage;
#ifdef DEBUG
friend class ReentrancyGuard;
@ -255,7 +255,11 @@ class Vector : private AllocPolicy
/* private accessors */
bool usingInlineStorage() const {
return mBegin == (T *)storage.addr();
return mBegin == inlineStorage();
}
T *inlineStorage() const {
return (T *)storage.addr();
}
T *beginNoCheck() const {
@ -427,7 +431,7 @@ class Vector : private AllocPolicy
internalAppendN(t, n);
}
template <class U> void infallibleAppend(const U *begin, const U *end) {
internalAppend(begin, PointerRangeSize(begin, end));
internalAppend(begin, mozilla::PointerRangeSize(begin, end));
}
template <class U> void infallibleAppend(const U *begin, size_t length) {
internalAppend(begin, length);
@ -479,6 +483,8 @@ class Vector : private AllocPolicy
* object (which must be heap-allocated) itself.
*/
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
void swap(Vector &other);
};
/* This does the re-entrancy check plus several other sanity checks. */
@ -506,6 +512,9 @@ template <class T, size_t N, class AllocPolicy>
JS_ALWAYS_INLINE
Vector<T, N, AllocPolicy>::Vector(MoveRef<Vector> rhs)
: AllocPolicy(rhs)
#ifdef DEBUG
, entered(false)
#endif
{
mLength = rhs->mLength;
mCapacity = rhs->mCapacity;
@ -856,7 +865,7 @@ JS_ALWAYS_INLINE bool
Vector<T,N,AP>::append(const U *insBegin, const U *insEnd)
{
REENTRANCY_GUARD_ET_AL;
size_t needed = PointerRangeSize(insBegin, insEnd);
size_t needed = mozilla::PointerRangeSize(insBegin, insEnd);
if (mLength + needed > mCapacity && !growStorageBy(needed))
return false;
@ -995,6 +1004,33 @@ Vector<T,N,AP>::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
}
template <class T, size_t N, class AP>
inline void
Vector<T,N,AP>::swap(Vector &other)
{
// TODO Implement N != 0
JS_STATIC_ASSERT(N == 0);
// This only works when inline storage is always empty.
if (!usingInlineStorage() && other.usingInlineStorage()) {
other.mBegin = mBegin;
mBegin = inlineStorage();
} else if (usingInlineStorage() && !other.usingInlineStorage()) {
mBegin = other.mBegin;
other.mBegin = other.inlineStorage();
} else if (!usingInlineStorage() && !other.usingInlineStorage()) {
Swap(mBegin, other.mBegin);
} else {
// This case is a no-op, since we'd set both to use their inline storage.
}
Swap(mLength, other.mLength);
Swap(mCapacity, other.mCapacity);
#ifdef DEBUG
Swap(mReserved, other.mReserved);
#endif
}
} /* namespace js */
#ifdef _MSC_VER

View File

@ -18,6 +18,8 @@ namespace js {
* - public copy constructor, assignment, destructor
* - void *malloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *calloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *realloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* The *used* bytes of the previous buffer is passed in
@ -33,6 +35,7 @@ class SystemAllocPolicy
{
public:
void *malloc_(size_t bytes) { return js_malloc(bytes); }
void *calloc_(size_t bytes) { return js_calloc(bytes); }
void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {}
@ -71,6 +74,13 @@ class TempAllocPolicy
return p;
}
void *calloc_(size_t bytes) {
void *p = js_calloc(bytes);
if (JS_UNLIKELY(!p))
p = onOutOfMemory(NULL, bytes);
return p;
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *p2 = js_realloc(p, bytes);
if (JS_UNLIKELY(!p2))

View File

@ -1 +1 @@
4f78a759104eea6e7790c03ce0130299eeaa3968
ba4ed5550f4042bc9963d0e15cce943b9f0be17a

View File

@ -13,7 +13,6 @@
#include "jsapi.h"
#include "jsprvtd.h"
#if defined(__cplusplus)
namespace JS {
struct FrameDescription
@ -47,9 +46,6 @@ JS_FRIEND_API(void) js_DumpValue(const js::Value &val);
JS_FRIEND_API(void) js_DumpId(jsid id);
JS_FRIEND_API(void) js_DumpStackFrame(JSContext *cx, js::StackFrame *start = NULL);
# endif
#endif
JS_BEGIN_EXTERN_C
JS_FRIEND_API(void)
js_DumpBacktrace(JSContext *cx);
@ -432,6 +428,4 @@ JS_UnwrapObjectAndInnerize(JSObject *obj);
extern JS_FRIEND_API(JSBool)
js_CallContextDebugHandler(JSContext *cx);
JS_END_EXTERN_C
#endif /* jsdbgapi_h___ */

View File

@ -14,8 +14,6 @@
#include "jstypes.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C
#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
#elif defined(XP_WIN)
@ -598,6 +596,4 @@ extern JS_PUBLIC_API(void)
JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp);
#endif
JS_END_EXTERN_C
#endif /* jsdhash_h___ */

View File

@ -8,12 +8,28 @@
#define jsfriendapi_h___
#include "jsclass.h"
#include "jscpucfg.h"
#include "jspubtd.h"
#include "jsprvtd.h"
#include "js/HeapAPI.h"
#include "mozilla/GuardObjects.h"
JS_BEGIN_EXTERN_C
/*
* This macro checks if the stack pointer has exceeded a given limit. If
* |tolerance| is non-zero, it returns true only if the stack pointer has
* exceeded the limit by more than |tolerance| bytes.
*/
#if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
((uintptr_t)(sp) < (limit)+(tolerance))
#else
# define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
((uintptr_t)(sp) > (limit)-(tolerance))
#endif
#define JS_CHECK_STACK_SIZE(limit, lval) JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, lval, 0)
extern JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
@ -139,8 +155,6 @@ extern JS_FRIEND_API(void)
js_DumpChars(const jschar *s, size_t n);
#endif
#ifdef __cplusplus
extern JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
@ -171,12 +185,6 @@ struct JSFunctionSpecWithHelp {
extern JS_FRIEND_API(bool)
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
typedef bool (* JS_SourceHook)(JSContext *cx, JSScript *script, jschar **src, uint32_t *length);
extern JS_FRIEND_API(void)
@ -184,6 +192,8 @@ JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
namespace js {
extern mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
inline JSRuntime *
GetRuntime(const JSContext *cx)
{
@ -259,15 +269,34 @@ TraceWeakMaps(WeakMapTracer *trc);
extern JS_FRIEND_API(bool)
GCThingIsMarkedGray(void *thing);
extern JS_FRIEND_API(bool)
AreGCGrayBitsValid(JSRuntime *rt);
/*
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JSTRACE_SHAPE. |thing| should be non-null.
*/
extern JS_FRIEND_API(void)
UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind);
typedef void
(GCThingCallback)(void *closure, void *gcthing);
(*GCThingCallback)(void *closure, void *gcthing);
extern JS_FRIEND_API(void)
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback callback, void *closure);
extern JS_FRIEND_API(JSObject *)
GetWeakmapKeyDelegate(JSObject *key);
JS_FRIEND_API(JSGCTraceKind)
GCThingTraceKind(void *thing);
/*
* Invoke cellCallback on every gray JS_OBJECT in the given compartment.
*/
extern JS_FRIEND_API(void)
IterateGrayObjects(JSCompartment *compartment, GCThingCallback cellCallback, void *data);
/*
* Shadow declarations of JS internal structures, for access by inline access
* functions below. Do not use these structures in any other way. When adding
@ -527,6 +556,12 @@ GetNativeStackLimit(const JSRuntime *rt)
return RuntimeFriendFields::get(rt)->nativeStackLimit;
}
/*
* These macros report a stack overflow and run |onerror| if we are close to
* using up the C stack. The JS_CHECK_CHROME_RECURSION variant gives us a little
* extra space so that we can ensure that crucial code is able to run.
*/
#define JS_CHECK_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
@ -536,6 +571,18 @@ GetNativeStackLimit(const JSRuntime *rt)
} \
JS_END_MACRO
#define JS_CHECK_CHROME_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE_WITH_TOLERANCE(js::GetNativeStackLimit(js::GetRuntime(cx)), \
&stackDummy_, \
1024 * sizeof(size_t))) \
{ \
js_ReportOverRecursed(cx); \
onerror; \
} \
JS_END_MACRO
JS_FRIEND_API(void)
StartPCCountProfiling(JSContext *cx);
@ -979,8 +1026,6 @@ uint32_t GetListBaseExpandoSlot();
} /* namespace js */
#endif
/* Implemented in jsdate.cpp. */
/*
@ -1017,8 +1062,6 @@ js_GetSCOffset(JSStructuredCloneWriter* writer);
/* Typed Array functions, implemented in jstypedarray.cpp */
#ifdef __cplusplus
namespace js {
namespace ArrayBufferView {
@ -1038,6 +1081,12 @@ enum ViewType {
*/
TYPE_UINT8_CLAMPED,
/*
* Type returned for a DataView. Note that there is no single element type
* in this case.
*/
TYPE_DATAVIEW,
TYPE_MAX
};
@ -1045,9 +1094,6 @@ enum ViewType {
} /* namespace js */
typedef js::ArrayBufferView::ViewType JSArrayBufferViewType;
#else
typedef uint32_t JSArrayBufferViewType;
#endif /* __cplusplus */
/*
* Create a new typed array with nelements elements.
@ -1150,41 +1196,40 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
* the various accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
JS_IsTypedArrayObject(JSObject *obj);
/*
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping. If this test or one of the more specific tests succeeds, then it
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
* below. cx MUST be non-NULL and valid.
* below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
JS_IsArrayBufferViewObject(JSObject *obj);
/*
* Test for specific typed array types (ArrayBufferView subtypes)
*/
extern JS_FRIEND_API(JSBool)
JS_IsInt8Array(JSObject *obj, JSContext *cx);
JS_IsInt8Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint8Array(JSObject *obj, JSContext *cx);
JS_IsUint8Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint8ClampedArray(JSObject *obj, JSContext *cx);
JS_IsUint8ClampedArray(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsInt16Array(JSObject *obj, JSContext *cx);
JS_IsInt16Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint16Array(JSObject *obj, JSContext *cx);
JS_IsUint16Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsInt32Array(JSObject *obj, JSContext *cx);
JS_IsInt32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint32Array(JSObject *obj, JSContext *cx);
JS_IsUint32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsFloat32Array(JSObject *obj, JSContext *cx);
JS_IsFloat32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
JS_IsFloat64Array(JSObject *obj);
/*
* Unwrap Typed arrays all at once. Return NULL without throwing if the object
@ -1192,38 +1237,37 @@ JS_IsFloat64Array(JSObject *obj, JSContext *cx);
* success, filling both outparameters.
*/
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data);
JS_GetObjectAsInt8Array(JSObject *obj, uint32_t *length, int8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsUint8Array(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsUint8ClampedArray(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data);
JS_GetObjectAsInt16Array(JSObject *obj, uint32_t *length, int16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data);
JS_GetObjectAsUint16Array(JSObject *obj, uint32_t *length, uint16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data);
JS_GetObjectAsInt32Array(JSObject *obj, uint32_t *length, int32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data);
JS_GetObjectAsUint32Array(JSObject *obj, uint32_t *length, uint32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data);
JS_GetObjectAsFloat32Array(JSObject *obj, uint32_t *length, float **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data);
JS_GetObjectAsFloat64Array(JSObject *obj, uint32_t *length, double **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data);
/*
* Get the type of elements in a typed array.
* Get the type of elements in a typed array, or TYPE_DATAVIEW if a DataView.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is an ArrayBufferView or a
* wrapper of an ArrayBufferView, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(JSArrayBufferViewType)
JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferViewType(JSObject *obj);
/*
* Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
@ -1232,18 +1276,17 @@ JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
* accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj, JSContext *maybecx);
JS_IsArrayBufferObject(JSObject *obj);
/*
* Return the available byte length of an array buffer.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* ArrayBuffer, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferByteLength(JSObject *obj);
/*
* Return a pointer to an array buffer's data. The buffer is still owned by the
@ -1252,22 +1295,20 @@ JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* ArrayBuffer, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferData(JSObject *obj);
/*
* Return the number of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
JS_GetTypedArrayLength(JSObject *obj);
/*
* Return the byte offset from the start of an array buffer to the start of a
@ -1275,22 +1316,20 @@ JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
JS_GetTypedArrayByteOffset(JSObject *obj);
/*
* Return the byte length of a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
JS_GetTypedArrayByteLength(JSObject *obj);
/*
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
@ -1298,13 +1337,13 @@ JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
* unwrapping.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
JS_IsArrayBufferViewObject(JSObject *obj);
/*
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
JS_GetArrayBufferViewByteLength(JSObject *obj);
/*
* Return a pointer to the start of the data referenced by a typed array. The
@ -1313,43 +1352,48 @@ JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
*
* |obj| must have passed a JS_Is*Array test, or somehow be known that it would
* pass such a test: it is a typed array or a wrapper of a typed array, and the
* unwrapping will succeed. If cx is NULL, then DEBUG builds may be unable to
* assert when unwrapping should be disallowed.
* unwrapping will succeed.
*/
extern JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt8ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint8ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint8ClampedArrayData(JSObject *obj);
extern JS_FRIEND_API(int16_t *)
JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt16ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint16_t *)
JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint16ArrayData(JSObject *obj);
extern JS_FRIEND_API(int32_t *)
JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt32ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint32_t *)
JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint32ArrayData(JSObject *obj);
extern JS_FRIEND_API(float *)
JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetFloat32ArrayData(JSObject *obj);
extern JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetFloat64ArrayData(JSObject *obj);
/*
* Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
* versions when possible.
*/
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferViewData(JSObject *obj);
/*
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
* throw an exception if a security wrapper is encountered that denies the
* operation.
* Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
* neutered, this will still return the neutered buffer. |obj| must be an
* object that would return true for JS_IsArrayBufferViewObject().
*/
extern JS_FRIEND_API(JSObject *)
JS_GetArrayBufferViewBuffer(JSObject *obj);
/*
* Check whether obj supports JS_GetDataView* APIs.
*/
JS_FRIEND_API(JSBool)
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
JS_IsDataViewObject(JSObject *obj);
/*
* Return the byte offset of a data view into its array buffer. |obj| must be a
@ -1357,11 +1401,10 @@ JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
*
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
* it would pass such a test: it is a data view or a wrapper of a data view,
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
* unable to assert when unwrapping should be disallowed.
* and the unwrapping will succeed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
JS_GetDataViewByteOffset(JSObject *obj);
/*
* Return the byte length of a data view.
@ -1372,7 +1415,7 @@ JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
JS_GetDataViewByteLength(JSObject *obj);
/*
* Return a pointer to the beginning of the data referenced by a DataView.
@ -1383,9 +1426,8 @@ JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(void *)
JS_GetDataViewData(JSObject *obj, JSContext *maybecx);
JS_GetDataViewData(JSObject *obj);
#ifdef __cplusplus
/*
* This struct contains metadata passed from the DOM to the JS Engine for JIT
* optimizations on DOM property accessors. Eventually, this should be made
@ -1420,15 +1462,16 @@ FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
}
/* Statically asserted in jsfun.h. */
static const unsigned JS_FUNCTION_INTERPRETED_BIT = 0x1;
static JS_ALWAYS_INLINE void
SET_JITINFO(JSFunction * func, const JSJitInfo *info)
{
js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
/* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */
JS_ASSERT(!(fun->flags & 0x4000));
JS_ASSERT(!(fun->flags & JS_FUNCTION_INTERPRETED_BIT));
fun->jitinfo = info;
}
#endif /* __cplusplus */
/*
* Engine-internal extensions of jsid. This code is here only until we
@ -1494,8 +1537,6 @@ JSID_TO_ATOM(jsid id)
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
#ifdef __cplusplus
namespace js {
static JS_ALWAYS_INLINE Value
@ -1517,8 +1558,12 @@ IdToJsval(jsid id)
return IdToValue(id);
}
extern JS_FRIEND_API(bool)
IsReadOnlyDateMethod(JS::IsAcceptableThis test, JS::NativeImpl method);
extern JS_FRIEND_API(bool)
IsTypedArrayThisCheck(JS::IsAcceptableThis test);
} /* namespace js */
#endif /* __cplusplus */
#endif /* jsfriendapi_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -38,25 +38,4 @@ typedef struct PRLock PRLock;
#endif /* JS_THREADSAFE */
namespace js {
class AutoAtomicIncrement
{
int32_t *p;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
AutoAtomicIncrement(int32_t *p JS_GUARD_OBJECT_NOTIFIER_PARAM)
: p(p) {
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_ATOMIC_INCREMENT(p);
}
~AutoAtomicIncrement() {
JS_ATOMIC_DECREMENT(p);
}
};
} /* namespace js */
#endif /* jslock_h___ */

View File

@ -38,7 +38,7 @@ enum DecodingMode { STRICT, LEGACY };
namespace js {
extern JS_FRIEND_API(JSBool)
ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, HandleValue filter,
ParseJSONWithReviver(JSContext *cx, JS::StableCharPtr chars, size_t length, HandleValue filter,
MutableHandleValue vp, DecodingMode decodingMode = STRICT);
} /* namespace js */

View File

@ -16,10 +16,9 @@
** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
** %s - string
** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
** %s - ascii string
** %hs - ucs2 string
** %c - character
** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
** %p - pointer (deals with machine dependent pointer size)
** %f - float
** %g - float
@ -28,8 +27,6 @@
#include <stdio.h>
#include <stdarg.h>
JS_BEGIN_EXTERN_C
/*
** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
** of the buffer. Returns the length of the written output, NOT including
@ -77,6 +74,4 @@ extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
extern JS_PUBLIC_API(uint32_t) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
JS_END_EXTERN_C
#endif /* jsprf_h___ */

View File

@ -60,5 +60,6 @@
macro(Set, 38, js_InitSetClass) \
macro(DataView, 39, js_InitTypedArrayClasses) \
macro(ParallelArray, 40, js_InitParallelArrayClass) \
macro(Intl, 41, js_InitIntlClass) \
#endif /* jsprototypes_h___ */

View File

@ -26,7 +26,9 @@ class JS_FRIEND_API(Wrapper);
*
* Proxy traps are grouped into fundamental and derived traps. Every proxy has
* to at least provide implementations for the fundamental traps, but the
* derived traps can be implemented in terms of the fundamental ones.
* derived traps can be implemented in terms of the fundamental ones
* BaseProxyHandler provides implementations of the derived traps in terms of
* the (pure virtual) fundamental traps.
*
* To minimize code duplication, a set of abstract proxy handler classes is
* provided, from which other handlers may inherit. These abstract classes
@ -34,9 +36,9 @@ class JS_FRIEND_API(Wrapper);
*
* BaseProxyHandler
* |
* IndirectProxyHandler
* |
* DirectProxyHandler
* |
* Wrapper
*/
/*
@ -69,20 +71,6 @@ class JS_FRIEND_API(BaseProxyHandler) {
return false;
}
/*
* The function Wrapper::wrapperHandler takes a pointer to a
* BaseProxyHandler and returns a pointer to a Wrapper if and only if the
* BaseProxyHandler is a wrapper handler (otherwise, it returns NULL).
*
* Unfortunately, we can't inherit Wrapper from BaseProxyHandler, since that
* would create a dreaded diamond, and we can't use dynamic_cast to cast
* BaseProxyHandler to Wrapper, since that would require us to compile with
* run-time type information. Hence the need for this virtual function.
*/
virtual Wrapper *toWrapper() {
return NULL;
}
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
bool set, PropertyDescriptor *desc) = 0;
@ -130,17 +118,14 @@ class JS_FRIEND_API(BaseProxyHandler) {
};
/*
* IndirectProxyHandler assumes that a target exists. Moreover, it assumes the
* target is a JSObject. Consequently, it provides default implementations for
* the fundamental traps that forward their behavior to the target. The derived
* traps, however, are inherited from BaseProxyHandler, and therefore still
* implemented in terms of the fundamental ones. This allows consumers of this
* class to define custom behavior without implementing the entire gamut of
* proxy traps.
* DirectProxyHandler includes a notion of a target object. All traps are
* reimplemented such that they forward their behavior to the target. This
* allows consumers of this class to forward to another object as transparently
* and efficiently as possible.
*/
class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
public:
explicit IndirectProxyHandler(void *family);
class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler {
public:
explicit DirectProxyHandler(void *family);
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
@ -158,11 +143,21 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
virtual bool enumerate(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc,
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, Value *vp) MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, bool strict, Value *vp) MOZ_OVERRIDE;
virtual bool keys(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc,
Value *argv, Value *rval) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
@ -182,33 +177,6 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
};
/*
* DirectProxyHandler has the same assumptions about the target as its base,
* IndirectProxyHandler. Its fundamental traps are inherited from this class,
* and therefore forward their behavior to the target. The derived traps,
* however, are overrided so that, they too, forward their behavior to the
* target. This allows consumers of this class to forward to another object as
* transparently as possible.
*/
class JS_PUBLIC_API(DirectProxyHandler) : public IndirectProxyHandler {
public:
explicit DirectProxyHandler(void *family);
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, Value *vp) MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, bool strict, Value *vp) MOZ_OVERRIDE;
virtual bool keys(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp) MOZ_OVERRIDE;
};
/* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */
class Proxy {
public:
@ -350,13 +318,12 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
JSObject *proto, JSObject *parent,
JSObject *call = NULL, JSObject *construct = NULL);
} /* namespace js */
JSObject *
RenewProxyObject(JSContext *cx, JSObject *obj, BaseProxyHandler *handler, Value priv);
JS_BEGIN_EXTERN_C
} /* namespace js */
extern JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, JSHandleObject obj);
JS_END_EXTERN_C
#endif

View File

@ -29,8 +29,6 @@
#include "js/Vector.h"
#endif
JS_BEGIN_EXTERN_C
/*
* Convenience constants.
*/
@ -129,7 +127,7 @@ class ScriptFrameIter;
class Proxy;
class JS_FRIEND_API(BaseProxyHandler);
class JS_FRIEND_API(DirectWrapper);
class JS_FRIEND_API(Wrapper);
class JS_FRIEND_API(CrossCompartmentWrapper);
class TempAllocPolicy;
@ -379,16 +377,5 @@ typedef JSObject *
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
/*
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
*/
#ifdef JS_C_STRINGS_ARE_UTF8
# define js_CStringsAreUTF8 JS_TRUE
#else
extern JSBool js_CStringsAreUTF8;
#endif
JS_END_EXTERN_C
#endif /* jsprvtd_h___ */

View File

@ -39,6 +39,8 @@ namespace JS { class Value; }
*/
#ifdef __cplusplus
#define JS_NO_JSVAL_JSID_STRUCT_TYPES
# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
# define JS_USE_JSID_STRUCT_TYPES
# endif
@ -60,8 +62,6 @@ typedef ptrdiff_t jsid;
# define JSID_BITS(id) (id)
#endif
JS_BEGIN_EXTERN_C
#ifdef WIN32
typedef wchar_t jschar;
#else
@ -217,8 +217,6 @@ typedef JSBool JSCallOnceType;
#endif
typedef JSBool (*JSInitCallback)(void);
JS_END_EXTERN_C
#ifdef __cplusplus
namespace js {
@ -311,14 +309,6 @@ struct RuntimeFriendFields {
/* Limit pointer for checking native stack consumption. */
uintptr_t nativeStackLimit;
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
RuntimeFriendFields()
: interrupt(0),
nativeStackLimit(0) { }
@ -328,6 +318,32 @@ struct RuntimeFriendFields {
}
};
class PerThreadData;
struct PerThreadDataFriendFields
{
PerThreadDataFriendFields();
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
static PerThreadDataFriendFields *get(js::PerThreadData *pt) {
return reinterpret_cast<PerThreadDataFriendFields *>(pt);
}
static PerThreadDataFriendFields *getMainThread(JSRuntime *rt) {
// mainThread must always appear directly after |RuntimeFriendFields|.
// Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
return reinterpret_cast<PerThreadDataFriendFields *>(
reinterpret_cast<char*>(rt) + sizeof(RuntimeFriendFields));
}
};
} /* namespace js */
#endif /* __cplusplus */

View File

@ -46,11 +46,11 @@
**
***********************************************************************/
#define JS_EXTERN_API(type) extern MOZ_EXPORT_API(type)
#define JS_EXPORT_API(type) MOZ_EXPORT_API(type)
#define JS_EXPORT_DATA(type) MOZ_EXPORT_DATA(type)
#define JS_IMPORT_API(type) MOZ_IMPORT_API(type)
#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA(type)
#define JS_EXTERN_API(type) extern MOZ_EXPORT type
#define JS_EXPORT_API(type) MOZ_EXPORT type
#define JS_EXPORT_DATA(type) MOZ_EXPORT type
#define JS_IMPORT_API(type) MOZ_IMPORT_API type
#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA type
/*
* The linkage of JS API functions differs depending on whether the file is
@ -62,11 +62,11 @@
# define JS_PUBLIC_API(t) t
# define JS_PUBLIC_DATA(t) t
#elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_PUBLIC_API(t) MOZ_EXPORT_API(t)
# define JS_PUBLIC_DATA(t) MOZ_EXPORT_DATA(t)
# define JS_PUBLIC_API(t) MOZ_EXPORT t
# define JS_PUBLIC_DATA(t) MOZ_EXPORT t
#else
# define JS_PUBLIC_API(t) MOZ_IMPORT_API(t)
# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA(t)
# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
#endif
#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
@ -181,8 +181,6 @@
#endif
JS_BEGIN_EXTERN_C
/************************************************************************
** TYPES: JSBool
** DESCRIPTION:
@ -282,6 +280,4 @@ typedef int JSBool;
# define JS_EXTENSION_(s) s
#endif
JS_END_EXTERN_C
#endif /* jstypes_h___ */

View File

@ -369,23 +369,23 @@ class Compressor
z_stream zs;
const unsigned char *inp;
size_t inplen;
size_t outbytes;
public:
Compressor(const unsigned char *inp, size_t inplen, unsigned char *out)
: inp(inp),
inplen(inplen)
{
JS_ASSERT(inplen > 0);
zs.opaque = NULL;
zs.next_in = (Bytef *)inp;
zs.avail_in = 0;
zs.next_out = out;
zs.avail_out = inplen;
}
enum Status {
MOREOUTPUT,
DONE,
CONTINUE,
OOM
};
Compressor(const unsigned char *inp, size_t inplen);
~Compressor();
bool init();
void setOutput(unsigned char *out, size_t outlen);
size_t outWritten() const { return outbytes; }
/* Compress some of the input. Return true if it should be called again. */
bool compressMore();
/* Finalize compression. Return the length of the compressed input. */
size_t finish();
Status compressMore();
};
/*

View File

@ -14,8 +14,6 @@
#include "js/Utility.h"
JS_BEGIN_EXTERN_C
/*
* Try to get jsvals 64-bit aligned. We could almost assert that all values are
* aligned, but MSVC and GCC occasionally break alignment.
@ -835,8 +833,6 @@ JS_CANONICALIZE_NAN(double d)
return d;
}
JS_END_EXTERN_C
#ifdef __cplusplus
static jsval_layout JSVAL_TO_IMPL(JS::Value);
static JS::Value IMPL_TO_JSVAL(jsval_layout);

View File

@ -170,4 +170,7 @@
MOZ_NOT_REACHED("don't call this! to be used in the new object representation")
#endif
/* ECMAScript Internationalization API isn't fully implemented yet. */
#define ENABLE_INTL_API 0
#endif /* jsversion_h___ */

View File

@ -18,36 +18,24 @@ namespace js {
class DummyFrameGuard;
/*
* A wrapper is essentially a proxy that restricts access to certain traps. The
* way in which a wrapper restricts access to its traps depends on the
* particular policy for that wrapper. To allow a wrapper's policy to be
* customized, the Wrapper base class contains two functions, enter/leave, which
* are called as a policy enforcement check before/after each trap is forwarded.
*
* To minimize code duplication, a set of abstract wrapper classes is
* provided, from which other wrappers may inherit. These abstract classes are
* organized in the following hierarchy:
*
* BaseProxyHandler Wrapper
* | | |
* IndirectProxyHandler | |
* | | | |
* | IndirectWrapper |
* | |
* DirectProxyHandler |
* | |
* DirectWrapper
* A wrapper is a proxy with a target object to which it generally forwards
* operations, but may restrict access to certain operations or instrument
* the trap operations in various ways. A wrapper is distinct from a Direct Proxy
* Handler in the sense that it can be "unwrapped" in C++, exposing the underlying
* object (Direct Proxy Handlers have an underlying target object, but don't
* expect to expose this object via any kind of unwrapping operation). Callers
* should be careful to avoid unwrapping security wrappers in the wrong context.
*/
class JS_FRIEND_API(Wrapper)
class JS_FRIEND_API(Wrapper) : public DirectProxyHandler
{
unsigned mFlags;
bool mSafeToUnwrap;
public:
enum Action {
GET,
SET,
CALL,
PUNCTURE
CALL
};
enum Flags {
@ -55,128 +43,42 @@ class JS_FRIEND_API(Wrapper)
LAST_USED_FLAG = CROSS_COMPARTMENT
};
typedef enum {
PermitObjectAccess,
PermitPropertyAccess,
DenyAccess
} Permission;
/*
* Wrappers can explicitly specify that they are unsafe to unwrap from a
* security perspective (as is the case for SecurityWrappers). If a wrapper
* is not safe to unwrap, operations requiring full access to the underlying
* object (via UnwrapObjectChecked) will throw. Otherwise, they will succeed.
*/
void setSafeToUnwrap(bool safe) { mSafeToUnwrap = safe; };
bool isSafeToUnwrap() { return mSafeToUnwrap; };
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
JSObject *parent, Wrapper *handler);
static JSObject *Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler);
static Wrapper *wrapperHandler(RawObject wrapper);
static JSObject *wrappedObject(RawObject wrapper);
explicit Wrapper(unsigned flags);
unsigned flags() const {
return mFlags;
}
/*
* The function Wrapper::New takes a pointer to a Wrapper as the handler
* object. It then passes it on to the function NewProxyObject, which
* expects a pointer to a BaseProxyHandler as the handler object. We don't
* want to change Wrapper::New to take a pointer to a BaseProxyHandler,
* because that would allow the creation of wrappers with non-wrapper
* handlers. Unfortunately, we can't inherit Wrapper from BaseProxyHandler,
* since that would create a dreaded diamond, and we can't use dynamic_cast
* to cast Wrapper to BaseProxyHandler, since that would require us to
* compile with run time type information. Hence the need for this virtual
* function.
*/
virtual BaseProxyHandler *toBaseProxyHandler() = 0;
/* Policy enforcement traps.
*
* enter() allows the policy to specify whether the caller may perform |act|
* on the underlying object's |id| property. In the case when |act| is CALL,
* |id| is generally JSID_VOID.
*
* The |act| parameter to enter() specifies the action being performed. GET,
* SET, and CALL are self-explanatory, but PUNCTURE requires more
* explanation:
*
* GET and SET allow for a very fine-grained security membrane, through
* which access can be granted or denied on a per-property, per-object, and
* per-action basis. Sometimes though, we just want to asks if we can access
* _everything_ behind the wrapper barrier. For example, when the structured
* clone algorithm runs up against a cross-compartment wrapper, it needs to
* know whether it can enter the compartment and keep cloning, or whether it
* should throw. This is the role of PUNCTURE.
*
* PUNCTURE allows the policy to specify whether the wrapper barrier may
* be lifted - that is to say, whether the caller is allowed to access
* anything that the wrapped object could access. This is a very powerful
* permission, and thus should generally be denied for security wrappers
* except under very special circumstances. When |act| is PUNCTURE, |id|
* should be JSID_VOID.
* The |act| parameter to enter() specifies the action being performed.
*/
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
bool *bp);
};
/*
* IndirectWrapper forwards its traps by forwarding them to
* IndirectProxyHandler. In effect, IndirectWrapper behaves the same as
* IndirectProxyHandler, except that it adds policy enforcement checks to each
* fundamental trap.
*/
class JS_FRIEND_API(IndirectWrapper) : public Wrapper,
public IndirectProxyHandler
{
public:
explicit IndirectWrapper(unsigned flags);
explicit Wrapper(unsigned flags, bool hasPrototype = false);
virtual BaseProxyHandler* toBaseProxyHandler() {
return this;
}
virtual Wrapper *toWrapper() {
return this;
}
/* ES5 Harmony fundamental wrapper traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
jsid id, bool set,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper,
jsid id, bool set,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JSObject *wrapper,
AutoIdVector &props) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
Value *vp) MOZ_OVERRIDE;
};
/*
* DirectWrapper forwards its traps by forwarding them to DirectProxyHandler.
* In effect, DirectWrapper behaves the same as DirectProxyHandler, except that
* it adds policy enforcement checks to each trap.
*/
class JS_FRIEND_API(DirectWrapper) : public Wrapper, public DirectProxyHandler
{
public:
explicit DirectWrapper(unsigned flags, bool hasPrototype = false);
virtual ~DirectWrapper();
virtual BaseProxyHandler* toBaseProxyHandler() {
return this;
}
virtual Wrapper *toWrapper() {
return this;
}
virtual ~Wrapper();
/* ES5 Harmony fundamental wrapper traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper,
@ -214,14 +116,14 @@ class JS_FRIEND_API(DirectWrapper) : public Wrapper, public DirectProxyHandler
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
Value *vp) MOZ_OVERRIDE;
static DirectWrapper singleton;
static DirectWrapper singletonWithPrototype;
static Wrapper singleton;
static Wrapper singletonWithPrototype;
static void *getWrapperFamily();
};
/* Base class for all cross compartment wrapper handlers. */
class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
{
public:
CrossCompartmentWrapper(unsigned flags, bool hasPrototype = false);
@ -280,13 +182,22 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
public:
SecurityWrapper(unsigned flags);
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Wrapper::Action act,
bool *bp) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
/*
* Allow our subclasses to select the superclass behavior they want without
* needing to specify an exact superclass.
*/
typedef Base Permissive;
typedef SecurityWrapper<Base> Restrictive;
};
typedef SecurityWrapper<DirectWrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
@ -327,7 +238,8 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
};
extern JSObject *
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
TransparentObjectWrapper(JSContext *cx, JSObject *existing, JSObject *obj,
JSObject *wrappedProto, JSObject *parent,
unsigned flags);
// Proxy family for wrappers. Public so that IsWrapper() can be fully inlined by
@ -352,16 +264,19 @@ UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
// code should never be unwrapping outer window wrappers, we always stop at
// outer windows.
JS_FRIEND_API(JSObject *)
UnwrapObjectChecked(JSContext *cx, RawObject obj);
UnwrapObjectChecked(RawObject obj);
// Unwrap only the outermost security wrapper, with the same semantics as
// above. This is the checked version of Wrapper::wrappedObject.
JS_FRIEND_API(JSObject *)
UnwrapOneChecked(JSContext *cx, HandleObject obj);
UnwrapOneChecked(RawObject obj);
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(RawObject obj);
bool
IsDeadProxyObject(RawObject obj);
JSObject *
NewDeadProxyObject(JSContext *cx, JSObject *parent);
@ -381,6 +296,34 @@ JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter);
/*
* This auto class should be used around any code, such as brain transplants,
* that may touch dead compartments. Brain transplants can cause problems
* because they operate on all compartments, whether live or dead. A brain
* transplant can cause a formerly dead object to be "reanimated" by causing a
* read or write barrier to be invoked on it during the transplant. In this way,
* a compartment becomes a zombie, kept alive by repeatedly consuming
* (transplanted) brains.
*
* To work around this issue, we observe when mark bits are set on objects in
* dead compartments. If this happens during a brain transplant, we do a full,
* non-incremental GC at the end of the brain transplant. This will clean up any
* objects that were improperly marked.
*/
struct JS_FRIEND_API(AutoMaybeTouchDeadCompartments)
{
// The version that takes an object just uses it for its runtime.
AutoMaybeTouchDeadCompartments(JSContext *cx);
AutoMaybeTouchDeadCompartments(JSObject *obj);
~AutoMaybeTouchDeadCompartments();
private:
JSRuntime *runtime;
unsigned markCount;
bool inIncremental;
bool manipulatingDeadCompartments;
};
} /* namespace js */
#endif

View File

@ -93,6 +93,8 @@
# endif
# if __GNUC_MINOR__ >= 4
# define MOZ_HAVE_CXX11_DELETE
# endif
# if __GNUC_MINOR__ >= 5
# define MOZ_HAVE_CXX11_ENUM_TYPE
# define MOZ_HAVE_CXX11_STRONG_ENUMS
# endif
@ -356,6 +358,9 @@
* supported, as with MOZ_ENUM_TYPE(). For simplicity, it is currently
* mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do
* not support it.
*
* Note that the workaround implemented here is not compatible with enums
* nested inside a class.
*/
#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS)
/* All compilers that support strong enums also support an explicit

View File

@ -13,6 +13,7 @@
#ifndef mozilla_BloomFilter_h_
#define mozilla_BloomFilter_h_
#include "mozilla/Assertions.h"
#include "mozilla/Likely.h"
#include "mozilla/StandardInteger.h"
#include "mozilla/Util.h"

View File

@ -385,13 +385,13 @@ IsSubValid(T x, T y)
}
template<typename T,
bool IsSigned = IsSigned<T>::value,
bool IsTSigned = IsSigned<T>::value,
bool TwiceBiggerTypeIsSupported =
IsSupported<typename TwiceBiggerType<T>::Type>::value>
struct IsMulValidImpl {};
template<typename T, bool IsSigned>
struct IsMulValidImpl<T, IsSigned, true>
template<typename T, bool IsTSigned>
struct IsMulValidImpl<T, IsTSigned, true>
{
static bool run(T x, T y)
{
@ -451,7 +451,7 @@ IsDivValid(T x, T y)
}
// This is just to shut up msvc warnings about negating unsigned ints.
template<typename T, bool IsSigned = IsSigned<T>::value>
template<typename T, bool IsTSigned = IsSigned<T>::value>
struct OppositeIfSignedImpl
{
static T run(T x) { return -x; }

View File

@ -0,0 +1,175 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* A set abstraction for enumeration values. */
#ifndef mozilla_EnumSet_h
#define mozilla_EnumSet_h
#include "mozilla/Assertions.h"
#include "mozilla/StandardInteger.h"
namespace mozilla {
/**
* EnumSet<T> is a set of values defined by an enumeration. It is implemented
* using a 32 bit mask for each value so it will only work for enums with an int
* representation less than 32. It works both for enum and enum class types.
*/
template<typename T>
class EnumSet
{
public:
EnumSet()
: mBitField(0)
{ }
EnumSet(T aEnum)
: mBitField(aEnum)
{ }
EnumSet(T aEnum1, T aEnum2)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2))
{ }
EnumSet(T aEnum1, T aEnum2, T aEnum3)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3))
{ }
EnumSet(T aEnum1, T aEnum2, T aEnum3, T aEnum4)
: mBitField(bitFor(aEnum1) |
bitFor(aEnum2) |
bitFor(aEnum3) |
bitFor(aEnum4))
{ }
EnumSet(const EnumSet& aEnumSet)
: mBitField(aEnumSet.mBitField)
{ }
/**
* Add an element
*/
void operator+=(T aEnum) {
mBitField |= bitFor(aEnum);
}
/**
* Add an element
*/
EnumSet<T> operator+(T aEnum) const {
EnumSet<T> result(*this);
result += aEnum;
return result;
}
/**
* Union
*/
void operator+=(const EnumSet<T> aEnumSet) {
mBitField |= aEnumSet.mBitField;
}
/**
* Union
*/
EnumSet<T> operator+(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result += aEnumSet;
return result;
}
/**
* Remove an element
*/
void operator-=(T aEnum) {
mBitField &= ~(bitFor(aEnum));
}
/**
* Remove an element
*/
EnumSet<T> operator-(T aEnum) const {
EnumSet<T> result(*this);
result -= aEnum;
return result;
}
/**
* Remove a set of elements
*/
void operator-=(const EnumSet<T> aEnumSet) {
mBitField &= ~(aEnumSet.mBitField);
}
/**
* Remove a set of elements
*/
EnumSet<T> operator-(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result -= aEnumSet;
return result;
}
/**
* Intersection
*/
void operator&=(const EnumSet<T> aEnumSet) {
mBitField &= aEnumSet.mBitField;
}
/**
* Intersection
*/
EnumSet<T> operator&(const EnumSet<T> aEnumSet) const {
EnumSet<T> result(*this);
result &= aEnumSet;
return result;
}
/**
* Equality
*/
bool operator==(const EnumSet<T> aEnumSet) const {
return mBitField == aEnumSet.mBitField;
}
/**
* Test is an element is contained in the set
*/
bool contains(T aEnum) const {
return mBitField & bitFor(aEnum);
}
/**
* Return the number of elements in the set
*/
uint8_t size() {
uint8_t count = 0;
for (uint32_t bitField = mBitField; bitField; bitField >>= 1) {
if (bitField & 1)
count++;
}
return count;
}
private:
static uint32_t bitFor(T aEnum) {
uint32_t bitNumber(aEnum);
MOZ_ASSERT(bitNumber < 32);
return 1U << bitNumber;
}
uint32_t mBitField;
};
} // namespace mozilla
#endif // mozilla_EnumSet_h_

View File

@ -66,7 +66,7 @@ namespace detail {
* For more details, and examples of using these macros, see
* https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
*/
class MOZ_EXPORT_API(GuardObjectNotifier)
class MOZ_EXPORT GuardObjectNotifier
{
private:
bool* statementDone;
@ -83,7 +83,7 @@ class MOZ_EXPORT_API(GuardObjectNotifier)
}
};
class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
class MOZ_EXPORT GuardObjectNotificationReceiver
{
private:
bool statementDone;

View File

@ -351,7 +351,7 @@ HashString(const wchar_t* str, size_t length)
* same result out of HashBytes as you would out of HashString.
*/
MOZ_WARN_UNUSED_RESULT
extern MFBT_API(uint32_t)
extern MFBT_API uint32_t
HashBytes(const void* bytes, size_t length);
} /* namespace mozilla */

View File

@ -13,6 +13,10 @@
* LinkedListElement<T>. A given object may be in only one linked list at a
* time.
*
* A LinkedListElement automatically removes itself from the list upon
* destruction, and a LinkedList will fatally assert in debug builds if it's
* non-empty when it's destructed.
*
* For example, you might use LinkedList in a simple observer list class as
* follows.
*
@ -36,6 +40,8 @@
* void removeObserver(Observer* observer) {
* // Will assert if |observer| is not part of some list.
* observer.remove();
* // Or, will assert if |observer| is not part of |list| specifically.
* // observer.removeFrom(list);
* }
*
* void notifyObservers(char* topic) {
@ -101,8 +107,19 @@ class LinkedListElement
LinkedListElement* prev;
const bool isSentinel;
LinkedListElement* thisDuringConstruction() { return this; }
public:
LinkedListElement() : next(this), prev(this), isSentinel(false) { }
LinkedListElement()
: next(thisDuringConstruction()),
prev(thisDuringConstruction()),
isSentinel(false)
{ }
~LinkedListElement() {
if (!isSentinel && isInList())
remove();
}
/*
* Get the next element in the list, or NULL if this is the last element in
@ -158,6 +175,15 @@ class LinkedListElement
prev = this;
}
/*
* Identical to remove(), but also asserts in debug builds that this element
* is in list.
*/
void removeFrom(const LinkedList<T>& list) {
list.assertContains(asT());
remove();
}
/*
* Return true if |this| part is of a linked list, and false otherwise.
*/
@ -175,11 +201,10 @@ class LinkedListElement
};
LinkedListElement(NodeKind nodeKind)
: next(this),
prev(this),
: next(thisDuringConstruction()),
prev(thisDuringConstruction()),
isSentinel(nodeKind == NODE_KIND_SENTINEL)
{
}
{ }
/*
* Return |this| cast to T* if we're a normal node, or return NULL if we're
@ -240,6 +265,10 @@ class LinkedList
public:
LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
~LinkedList() {
MOZ_ASSERT(isEmpty());
}
/*
* Add elem to the front of the list.
*/
@ -375,6 +404,21 @@ class LinkedList
}
private:
friend class LinkedListElement<T>;
void assertContains(const T* t) const {
#ifdef DEBUG
for (const T* elem = getFirst();
elem;
elem = elem->getNext())
{
if (elem == t)
return;
}
MOZ_NOT_REACHED("element wasn't found in this list!");
#endif
}
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
};

View File

@ -20,7 +20,7 @@
# endif
#elif defined(__GNUC__)
# if defined(_GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if (__GNUC__ * 1000 + __GNU_MINOR__) >= 4006
# if (__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006
# define MOZ_HAVE_CXX11_NULLPTR
# endif
# endif

View File

@ -128,13 +128,13 @@ class RangedPtr
RangedPtr<T> operator+(size_t inc) {
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
MOZ_ASSERT(ptr + inc > ptr);
MOZ_ASSERT(ptr + inc >= ptr);
return create(ptr + inc);
}
RangedPtr<T> operator-(size_t dec) {
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
MOZ_ASSERT(ptr - dec < ptr);
MOZ_ASSERT(ptr - dec <= ptr);
return create(ptr - dec);
}

View File

@ -5,30 +5,36 @@
/* Simple class for computing SHA1. */
/*
* To compute the SHA1 of a buffer using this class you should write something
* like:
* void SHA1(const uint8_t* buf, unsigned size, uint8_t hash[20])
* {
* SHA1Sum S;
* S.update(buf, size);
* S.finish(hash);
* }
* If there are multiple buffers or chunks, the update method can be called
* multiple times and the SHA1 is computed on the concatenation of all the
* buffers passed to it.
* The finish method may only be called once and cannot be followed by calls
* to update.
*/
#ifndef mozilla_SHA1_h_
#define mozilla_SHA1_h_
#include "mozilla/StandardInteger.h"
#include "mozilla/Types.h"
#include <stddef.h>
namespace mozilla {
class SHA1Sum {
/**
* This class computes the SHA1 hash of a byte sequence, or of the concatenation
* of multiple sequences. For example, computing the SHA1 of two sequences of
* bytes could be done as follows:
*
* void SHA1(const uint8_t* buf1, uint32_t size1,
* const uint8_t* buf2, uint32_t size2,
* SHA1Sum::Hash& hash)
* {
* SHA1Sum s;
* s.update(buf1, size1);
* s.update(buf2, size2);
* s.finish(hash);
* }
*
* The finish method may only be called once and cannot be followed by calls
* to update.
*/
class SHA1Sum
{
union {
uint32_t w[16]; /* input buffer */
uint8_t b[64];
@ -37,12 +43,19 @@ class SHA1Sum {
unsigned H[22]; /* 5 state variables, 16 tmp values, 1 extra */
bool mDone;
public:
static const unsigned int HashSize = 20;
MFBT_API() SHA1Sum();
MFBT_API(void) update(const void* dataIn, uint32_t len);
MFBT_API(void) finish(uint8_t hashout[20]);
public:
MFBT_API SHA1Sum();
static const size_t HashSize = 20;
typedef uint8_t Hash[HashSize];
/* Add len bytes of dataIn to the data sequence being hashed. */
MFBT_API void update(const void* dataIn, uint32_t len);
/* Compute the final hash of all data into hashOut. */
MFBT_API void finish(SHA1Sum::Hash& hashOut);
};
}
} /* namespace mozilla */
#endif /* mozilla_SHA1_h_ */

View File

@ -9,6 +9,25 @@
namespace mozilla {
namespace detail {
/**
* The trickery used to implement IsBaseOf here makes it possible to use it for
* the cases of private and multiple inheritance. This code was inspired by the
* sample code here:
*
* http://stackoverflow.com/questions/2910979/how-is-base-of-works
*/
template<class Base, class Derived>
class IsBaseOfHelper
{
public:
operator Base*() const;
operator Derived*();
};
} /* namespace detail */
/*
* IsBaseOf allows to know whether a given class is derived from another.
*
@ -25,12 +44,47 @@ template<class Base, class Derived>
class IsBaseOf
{
private:
static char test(Base* b);
static int test(...);
template<class T>
static char test(Derived*, T);
static int test(Base*, int);
public:
static const bool value =
sizeof(test(static_cast<Derived*>(0))) == sizeof(char);
sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char);
};
template<class Base, class Derived>
class IsBaseOf<Base, const Derived>
{
private:
template<class T>
static char test(Derived*, T);
static int test(Base*, int);
public:
static const bool value =
sizeof(test(detail::IsBaseOfHelper<Base, Derived>(), int())) == sizeof(char);
};
template<class Base, class Derived>
class IsBaseOf<Base&, Derived&>
{
public:
static const bool value = false;
};
template<class Type>
class IsBaseOf<Type, Type>
{
public:
static const bool value = true;
};
template<class Type>
class IsBaseOf<Type, const Type>
{
public:
static const bool value = true;
};
/*

View File

@ -27,63 +27,60 @@
/* Implement compiler and linker macros needed for APIs. */
/*
* MOZ_EXPORT_API is used to declare and define a method which is externally
* MOZ_EXPORT is used to declare and define a symbol or type which is externally
* visible to users of the current library. It encapsulates various decorations
* needed to properly export the method's symbol. MOZ_EXPORT_DATA serves the
* same purpose for data.
* needed to properly export the method's symbol.
*
* api.h:
* extern MOZ_EXPORT_API(int) MeaningOfLife(void);
* extern MOZ_EXPORT_DATA(int) LuggageCombination;
* extern MOZ_EXPORT int MeaningOfLife(void);
* extern MOZ_EXPORT int LuggageCombination;
*
* api.c:
* MOZ_EXPORT_API(int) MeaningOfLife(void) { return 42; }
* MOZ_EXPORT_DATA(int) LuggageCombination = 12345;
* int MeaningOfLife(void) { return 42; }
* int LuggageCombination = 12345;
*
* If you are merely sharing a method across files, just use plain |extern|.
* These macros are designed for use by library interfaces -- not for normal
* methods or data used cross-file.
*/
#if defined(WIN32) || defined(XP_OS2)
# define MOZ_EXPORT_API(type) __declspec(dllexport) type
# define MOZ_EXPORT_DATA(type) __declspec(dllexport) type
# define MOZ_EXPORT __declspec(dllexport)
#else /* Unix */
# ifdef HAVE_VISIBILITY_ATTRIBUTE
# define MOZ_EXTERNAL_VIS __attribute__((visibility("default")))
# define MOZ_EXPORT __attribute__((visibility("default")))
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# define MOZ_EXTERNAL_VIS __global
# define MOZ_EXPORT __global
# else
# define MOZ_EXTERNAL_VIS
# define MOZ_EXPORT /* nothing */
# endif
# define MOZ_EXPORT_API(type) MOZ_EXTERNAL_VIS type
# define MOZ_EXPORT_DATA(type) MOZ_EXTERNAL_VIS type
#endif
/*
* Whereas implementers use MOZ_EXPORT_API and MOZ_EXPORT_DATA to declare and
* define library symbols, users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to
* access them. Most often the implementer of the library will expose an API
* macro which expands to either the export or import version of the macro,
* depending upon the compilation mode.
* Whereas implementers use MOZ_EXPORT to declare and define library symbols,
* users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to access them. Most often the
* implementer of the library will expose an API macro which expands to either
* the export or import version of the macro, depending upon the compilation
* mode.
*/
#ifdef _WIN32
# if defined(__MWERKS__)
# define MOZ_IMPORT_API(x) x
# define MOZ_IMPORT_API /* nothing */
# else
# define MOZ_IMPORT_API(x) __declspec(dllimport) x
# define MOZ_IMPORT_API __declspec(dllimport)
# endif
#elif defined(XP_OS2)
# define MOZ_IMPORT_API(x) __declspec(dllimport) x
# define MOZ_IMPORT_API __declspec(dllimport)
#else
# define MOZ_IMPORT_API(x) MOZ_EXPORT_API(x)
# define MOZ_IMPORT_API MOZ_EXPORT
#endif
#if defined(_WIN32) && !defined(__MWERKS__)
# define MOZ_IMPORT_DATA(x) __declspec(dllimport) x
# define MOZ_IMPORT_DATA __declspec(dllimport)
#elif defined(XP_OS2)
# define MOZ_IMPORT_DATA(x) __declspec(dllimport) x
# define MOZ_IMPORT_DATA __declspec(dllimport)
#else
# define MOZ_IMPORT_DATA(x) MOZ_EXPORT_DATA(x)
# define MOZ_IMPORT_DATA MOZ_EXPORT
#endif
/*
@ -92,19 +89,22 @@
* declarations when using mfbt.
*/
#if defined(IMPL_MFBT)
# define MFBT_API(type) MOZ_EXPORT_API(type)
# define MFBT_DATA(type) MOZ_EXPORT_DATA(type)
# define MFBT_API MOZ_EXPORT
# define MFBT_DATA MOZ_EXPORT
#else
/*
* When mozglue is linked in the program, we need the MFBT API symbols
* to be weak.
* On linux mozglue is linked in the program and we link libxul.so with
* -z,defs. Normally that causes the linker to reject undefined references in
* libxul.so, but as a loophole it allows undefined references to weak
* symbols. We add the weak attribute to the import version of the MFBT API
* macros to exploit this.
*/
# if defined(MOZ_GLUE_IN_PROGRAM)
# define MFBT_API(type) __attribute__((weak)) MOZ_IMPORT_API(type)
# define MFBT_DATA(type) __attribute__((weak)) MOZ_IMPORT_DATA(type)
# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API
# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA
# else
# define MFBT_API(type) MOZ_IMPORT_API(type)
# define MFBT_DATA(type) MOZ_IMPORT_DATA(type)
# define MFBT_API MOZ_IMPORT_API
# define MFBT_DATA MOZ_IMPORT_DATA
# endif
#endif
@ -117,7 +117,7 @@
*
* MOZ_BEGIN_EXTERN_C
*
* extern MOZ_EXPORT_API(int) MostRandomNumber(void);
* extern MOZ_EXPORT int MostRandomNumber(void);
* ...other declarations...
*
* MOZ_END_EXTERN_C

View File

@ -126,6 +126,10 @@ class WeakPtr
return ref->get();
}
T* get() const {
return ref->get();
}
private:
friend class SupportsWeakPtr<T>;

View File

@ -1 +1 @@
0b43ca82a2e3c648187f17aa0ea261a8d98ac2a5
50e1e403ec323943f3ab7274127546140d2d5d0a

View File

@ -1 +1 @@
04eff728bf10911147107d4237d102d9b96067e7
60e397be69b5e1699754e996d4392c0e1b8a154c

View File

@ -1,659 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsgc_barrier_h___
#define jsgc_barrier_h___
#include "jsapi.h"
#include "gc/Heap.h"
#include "gc/Root.h"
#include "js/HashTable.h"
/*
* A write barrier is a mechanism used by incremental or generation GCs to
* ensure that every value that needs to be marked is marked. In general, the
* write barrier should be invoked whenever a write can cause the set of things
* traced through by the GC to change. This includes:
* - writes to object properties
* - writes to array slots
* - writes to fields like JSObject::shape_ that we trace through
* - writes to fields in private data, like JSGenerator::obj
* - writes to non-markable fields like JSObject::private that point to
* markable data
* The last category is the trickiest. Even though the private pointers does not
* point to a GC thing, changing the private pointer may change the set of
* objects that are traced by the GC. Therefore it needs a write barrier.
*
* Every barriered write should have the following form:
* <pre-barrier>
* obj->field = value; // do the actual write
* <post-barrier>
* The pre-barrier is used for incremental GC and the post-barrier is for
* generational GC.
*
* PRE-BARRIER
*
* To understand the pre-barrier, let's consider how incremental GC works. The
* GC itself is divided into "slices". Between each slice, JS code is allowed to
* run. Each slice should be short so that the user doesn't notice the
* interruptions. In our GC, the structure of the slices is as follows:
*
* 1. ... JS work, which leads to a request to do GC ...
* 2. [first GC slice, which performs all root marking and possibly more marking]
* 3. ... more JS work is allowed to run ...
* 4. [GC mark slice, which runs entirely in drainMarkStack]
* 5. ... more JS work ...
* 6. [GC mark slice, which runs entirely in drainMarkStack]
* 7. ... more JS work ...
* 8. [GC marking finishes; sweeping done non-incrementally; GC is done]
* 9. ... JS continues uninterrupted now that GC is finishes ...
*
* Of course, there may be a different number of slices depending on how much
* marking is to be done.
*
* The danger inherent in this scheme is that the JS code in steps 3, 5, and 7
* might change the heap in a way that causes the GC to collect an object that
* is actually reachable. The write barrier prevents this from happening. We use
* a variant of incremental GC called "snapshot at the beginning." This approach
* guarantees the invariant that if an object is reachable in step 2, then we
* will mark it eventually. The name comes from the idea that we take a
* theoretical "snapshot" of all reachable objects in step 2; all objects in
* that snapshot should eventually be marked. (Note that the write barrier
* verifier code takes an actual snapshot.)
*
* The basic correctness invariant of a snapshot-at-the-beginning collector is
* that any object reachable at the end of the GC (step 9) must either:
* (1) have been reachable at the beginning (step 2) and thus in the snapshot
* (2) or must have been newly allocated, in steps 3, 5, or 7.
* To deal with case (2), any objects allocated during an incremental GC are
* automatically marked black.
*
* This strategy is actually somewhat conservative: if an object becomes
* unreachable between steps 2 and 8, it would be safe to collect it. We won't,
* mainly for simplicity. (Also, note that the snapshot is entirely
* theoretical. We don't actually do anything special in step 2 that we wouldn't
* do in a non-incremental GC.
*
* It's the pre-barrier's job to maintain the snapshot invariant. Consider the
* write "obj->field = value". Let the prior value of obj->field be
* value0. Since it's possible that value0 may have been what obj->field
* contained in step 2, when the snapshot was taken, the barrier marks
* value0. Note that it only does this if we're in the middle of an incremental
* GC. Since this is rare, the cost of the write barrier is usually just an
* extra branch.
*
* In practice, we implement the pre-barrier differently based on the type of
* value0. E.g., see JSObject::writeBarrierPre, which is used if obj->field is
* a JSObject*. It takes value0 as a parameter.
*
* POST-BARRIER
*
* These are not yet implemented. Once we get generational GC, they will allow
* us to keep track of pointers from non-nursery space into the nursery.
*
* IMPLEMENTATION DETAILS
*
* Since it would be awkward to change every write to memory into a function
* call, this file contains a bunch of C++ classes and templates that use
* operator overloading to take care of barriers automatically. In many cases,
* all that's necessary to make some field be barriered is to replace
* Type *field;
* with
* HeapPtr<Type> field;
* There are also special classes HeapValue and HeapId, which barrier js::Value
* and jsid, respectively.
*
* One additional note: not all object writes need to be barriered. Writes to
* newly allocated objects do not need a pre-barrier. In these cases, we use
* the "obj->field.init(value)" method instead of "obj->field = value". We use
* the init naming idiom in many places to signify that a field is being
* assigned for the first time.
*/
struct JSXML;
namespace js {
template<class T, typename Unioned = uintptr_t>
class EncapsulatedPtr
{
protected:
union {
T *value;
Unioned other;
};
public:
EncapsulatedPtr() : value(NULL) {}
EncapsulatedPtr(T *v) : value(v) {}
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
~EncapsulatedPtr() { pre(); }
/* Use to set the pointer to NULL. */
void clear() {
pre();
value = NULL;
}
EncapsulatedPtr<T, Unioned> &operator=(T *v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
return *this;
}
EncapsulatedPtr<T, Unioned> &operator=(const EncapsulatedPtr<T> &v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
value = v.value;
return *this;
}
/* Use this if the automatic coercion to T* isn't working. */
T *get() const { return value; }
/*
* Use these if you want to change the value without invoking the barrier.
* Obviously this is dangerous unless you know the barrier is not needed.
*/
T **unsafeGet() { return &value; }
void unsafeSet(T *v) { value = v; }
Unioned *unsafeGetUnioned() { return &other; }
T &operator*() const { return *value; }
T *operator->() const { return value; }
operator T*() const { return value; }
protected:
void pre();
};
template <class T, class Unioned = uintptr_t>
class HeapPtr : public EncapsulatedPtr<T, Unioned>
{
public:
HeapPtr() : EncapsulatedPtr<T>(NULL) {}
explicit HeapPtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
explicit HeapPtr(const HeapPtr<T> &v)
: EncapsulatedPtr<T>(v) { post(); }
void init(T *v) {
JS_ASSERT(!IsPoisonedPtr<T>(v));
this->value = v;
post();
}
HeapPtr<T, Unioned> &operator=(T *v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
this->value = v;
post();
return *this;
}
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
this->value = v.value;
post();
return *this;
}
protected:
void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
/* Make this friend so it can access pre() and post(). */
template<class T1, class T2>
friend inline void
BarrieredSetPair(JSCompartment *comp,
HeapPtr<T1> &v1, T1 *val1,
HeapPtr<T2> &v2, T2 *val2);
};
/*
* FixedHeapPtr is designed for one very narrow case: replacing immutable raw
* pointers to GC-managed things, implicitly converting to a handle type for
* ease of use. Pointers encapsulated by this type must:
*
* be immutable (no incremental write barriers),
* never point into the nursery (no generational write barriers), and
* be traced via MarkRuntime (we use fromMarkedLocation).
*
* In short: you *really* need to know what you're doing before you use this
* class!
*/
template <class T>
class FixedHeapPtr
{
T *value;
public:
operator T*() const { return value; }
T * operator->() const { return value; }
operator Handle<T*>() const {
return Handle<T*>::fromMarkedLocation(&value);
}
void init(T *ptr) {
value = ptr;
}
};
template <class T>
class RelocatablePtr : public EncapsulatedPtr<T>
{
public:
RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) {
if (v)
post();
}
explicit RelocatablePtr(const RelocatablePtr<T> &v) : EncapsulatedPtr<T>(v) {
if (this->value)
post();
}
~RelocatablePtr() {
if (this->value)
relocate(this->value->compartment());
}
RelocatablePtr<T> &operator=(T *v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
if (v) {
this->value = v;
post();
} else if (this->value) {
JSCompartment *comp = this->value->compartment();
this->value = v;
relocate(comp);
}
return *this;
}
RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
if (v.value) {
this->value = v.value;
post();
} else if (this->value) {
JSCompartment *comp = this->value->compartment();
this->value = v;
relocate(comp);
}
return *this;
}
protected:
inline void post();
inline void relocate(JSCompartment *comp);
};
/*
* This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
* barriers with only one branch to check if we're in an incremental GC.
*/
template<class T1, class T2>
static inline void
BarrieredSetPair(JSCompartment *comp,
HeapPtr<T1> &v1, T1 *val1,
HeapPtr<T2> &v2, T2 *val2)
{
if (T1::needWriteBarrierPre(comp)) {
v1.pre();
v2.pre();
}
v1.unsafeSet(val1);
v2.unsafeSet(val2);
v1.post();
v2.post();
}
struct Shape;
class BaseShape;
namespace types { struct TypeObject; }
typedef EncapsulatedPtr<JSObject> EncapsulatedPtrObject;
typedef EncapsulatedPtr<JSScript> EncapsulatedPtrScript;
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
typedef HeapPtr<JSObject> HeapPtrObject;
typedef HeapPtr<JSFunction> HeapPtrFunction;
typedef HeapPtr<JSString> HeapPtrString;
typedef HeapPtr<JSScript> HeapPtrScript;
typedef HeapPtr<Shape> HeapPtrShape;
typedef HeapPtr<BaseShape> HeapPtrBaseShape;
typedef HeapPtr<types::TypeObject> HeapPtrTypeObject;
typedef HeapPtr<JSXML> HeapPtrXML;
/* Useful for hashtables with a HeapPtr as key. */
template<class T>
struct HeapPtrHasher
{
typedef HeapPtr<T> Key;
typedef T *Lookup;
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
};
/* Specialized hashing policy for HeapPtrs. */
template <class T>
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
template<class T>
struct EncapsulatedPtrHasher
{
typedef EncapsulatedPtr<T> Key;
typedef T *Lookup;
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
static bool match(const Key &k, Lookup l) { return k.get() == l; }
};
template <class T>
struct DefaultHasher< EncapsulatedPtr<T> > : EncapsulatedPtrHasher<T> { };
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
{
protected:
Value value;
/*
* Ensure that EncapsulatedValue is not constructable, except by our
* implementations.
*/
EncapsulatedValue() MOZ_DELETE;
EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
EncapsulatedValue(const Value &v) : value(v) {}
~EncapsulatedValue() {}
public:
bool operator==(const EncapsulatedValue &v) const { return value == v.value; }
bool operator!=(const EncapsulatedValue &v) const { return value != v.value; }
const Value &get() const { return value; }
Value *unsafeGet() { return &value; }
operator const Value &() const { return value; }
JSGCTraceKind gcKind() const { return value.gcKind(); }
uint64_t asRawBits() const { return value.asRawBits(); }
static inline void writeBarrierPre(const Value &v);
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
protected:
inline void pre();
inline void pre(JSCompartment *comp);
private:
friend class ValueOperations<EncapsulatedValue>;
const Value * extract() const { return &value; }
};
class HeapValue : public EncapsulatedValue
{
public:
explicit inline HeapValue();
explicit inline HeapValue(const Value &v);
explicit inline HeapValue(const HeapValue &v);
inline ~HeapValue();
inline void init(const Value &v);
inline void init(JSCompartment *comp, const Value &v);
inline HeapValue &operator=(const Value &v);
inline HeapValue &operator=(const HeapValue &v);
/*
* This is a faster version of operator=. Normally, operator= has to
* determine the compartment of the value before it can decide whether to do
* the barrier. If you already know the compartment, it's faster to pass it
* in.
*/
inline void set(JSCompartment *comp, const Value &v);
static inline void writeBarrierPost(const Value &v, Value *addr);
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
private:
inline void post();
inline void post(JSCompartment *comp);
};
class RelocatableValue : public EncapsulatedValue
{
public:
explicit inline RelocatableValue();
explicit inline RelocatableValue(const Value &v);
inline RelocatableValue(const RelocatableValue &v);
inline ~RelocatableValue();
inline RelocatableValue &operator=(const Value &v);
inline RelocatableValue &operator=(const RelocatableValue &v);
private:
inline void post();
inline void post(JSCompartment *comp);
inline void relocate();
};
class HeapSlot : public EncapsulatedValue
{
/*
* Operator= is not valid for HeapSlot because is must take the object and
* slot offset to provide to the post/generational barrier.
*/
inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
public:
explicit inline HeapSlot() MOZ_DELETE;
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
inline ~HeapSlot();
inline void init(JSObject *owner, uint32_t slot, const Value &v);
inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
inline void set(JSObject *owner, uint32_t slot, const Value &v);
inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slot);
private:
inline void post(JSObject *owner, uint32_t slot);
inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
};
/*
* NOTE: This is a placeholder for bug 619558.
*
* Run a post write barrier that encompasses multiple contiguous slots in a
* single step.
*/
inline void
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count);
/*
* This is a post barrier for HashTables whose key can be moved during a GC.
*/
template <class Map, class Key>
inline void
HashTableWriteBarrierPost(JSCompartment *comp, const Map *map, const Key &key)
{
#ifdef JS_GCGENERATIONAL
if (key && comp->gcNursery.isInside(key))
comp->gcStoreBuffer.putGeneric(HashKeyRef(map, key));
#endif
}
static inline const Value *
Valueify(const EncapsulatedValue *array)
{
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
return (const Value *)array;
}
static inline HeapValue *
HeapValueify(Value *v)
{
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
return (HeapValue *)v;
}
class HeapSlotArray
{
HeapSlot *array;
public:
HeapSlotArray(HeapSlot *array) : array(array) {}
operator const Value *() const { return Valueify(array); }
operator HeapSlot *() const { return array; }
HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
};
class EncapsulatedId
{
protected:
jsid value;
private:
EncapsulatedId(const EncapsulatedId &v) MOZ_DELETE;
public:
explicit EncapsulatedId() : value(JSID_VOID) {}
explicit EncapsulatedId(jsid id) : value(id) {}
~EncapsulatedId();
inline EncapsulatedId &operator=(const EncapsulatedId &v);
bool operator==(jsid id) const { return value == id; }
bool operator!=(jsid id) const { return value != id; }
jsid get() const { return value; }
jsid *unsafeGet() { return &value; }
operator jsid() const { return value; }
protected:
inline void pre();
};
class RelocatableId : public EncapsulatedId
{
public:
explicit RelocatableId() : EncapsulatedId() {}
explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {}
inline ~RelocatableId();
inline RelocatableId &operator=(jsid id);
inline RelocatableId &operator=(const RelocatableId &v);
};
class HeapId : public EncapsulatedId
{
public:
explicit HeapId() : EncapsulatedId() {}
explicit inline HeapId(jsid id);
inline ~HeapId();
inline void init(jsid id);
inline HeapId &operator=(jsid id);
inline HeapId &operator=(const HeapId &v);
private:
inline void post();
HeapId(const HeapId &v) MOZ_DELETE;
};
/*
* Incremental GC requires that weak pointers have read barriers. This is mostly
* an issue for empty shapes stored in JSCompartment. The problem happens when,
* during an incremental GC, some JS code stores one of the compartment's empty
* shapes into an object already marked black. Normally, this would not be a
* problem, because the empty shape would have been part of the initial snapshot
* when the GC started. However, since this is a weak pointer, it isn't. So we
* may collect the empty shape even though a live object points to it. To fix
* this, we mark these empty shapes black whenever they get read out.
*/
template<class T>
class ReadBarriered
{
T *value;
public:
ReadBarriered() : value(NULL) {}
ReadBarriered(T *value) : value(value) {}
T *get() const {
if (!value)
return NULL;
T::readBarrier(value);
return value;
}
operator T*() const { return get(); }
T &operator*() const { return *get(); }
T *operator->() const { return get(); }
T **unsafeGet() { return &value; }
void set(T *v) { value = v; }
operator bool() { return !!value; }
};
class ReadBarrieredValue
{
Value value;
public:
ReadBarrieredValue() : value(UndefinedValue()) {}
ReadBarrieredValue(const Value &value) : value(value) {}
inline const Value &get() const;
Value *unsafeGet() { return &value; }
inline operator const Value &() const;
inline JSObject &toObject() const;
};
namespace tl {
template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
{ static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapSlot> { static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
template <> struct IsRelocatableHeapType<HeapId> { static const bool result = false; };
} /* namespace tl */
} /* namespace js */
#endif /* jsgc_barrier_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -77,8 +77,14 @@ class MutableHandleBase {};
namespace JS {
class AutoAssertNoGC;
template <typename T> class MutableHandle;
JS_FRIEND_API(void) EnterAssertNoGCScope();
JS_FRIEND_API(void) LeaveAssertNoGCScope();
JS_FRIEND_API(bool) InNoGCScope();
/*
* Handle provides an implicit constructor for NullPtr so that, given:
* foo(Handle<JSObject*> h);
@ -316,6 +322,169 @@ class InternalHandle<T*>
}
};
#ifdef DEBUG
template <typename T>
class IntermediateNoGC
{
T t_;
public:
IntermediateNoGC(const T &t) : t_(t) {
EnterAssertNoGCScope();
}
IntermediateNoGC(const IntermediateNoGC &) {
EnterAssertNoGCScope();
}
~IntermediateNoGC() {
LeaveAssertNoGCScope();
}
const T &operator->() { return t_; }
operator const T &() { return t_; }
};
#endif
/*
* Return<T> wraps GC things that are returned from accessor methods. The
* wrapper helps to ensure correct rooting of the returned pointer and safe
* access while unrooted.
*
* Example usage in a method declaration:
*
* class Foo {
* HeapPtrScript script_;
* ...
* public:
* Return<JSScript*> script() { return script_; }
* };
*
* Example usage of method (1):
*
* Foo foo(...);
* RootedScript script(cx, foo->script());
*
* Example usage of method (2):
*
* Foo foo(...);
* foo->script()->needsArgsObj();
*
* The purpose of this class is to assert eagerly on incorrect use of GC thing
* pointers. For example:
*
* RootedShape shape(cx, ...);
* shape->parent.init(js_NewGCThing<Shape*>(cx, ...));
*
* In this expression, C++ is allowed to order these calls as follows:
*
* Call Effect
* ---- ------
* 1) RootedShape::operator-> Stores shape::ptr_ to stack.
* 2) js_NewGCThing<Shape*> Triggers GC and compaction of shapes. This
* moves shape::ptr_ to a new location.
* 3) HeapPtrObject::init This call takes the relocated shape::ptr_
* as |this|, crashing or, worse, corrupting
* the program's state on the first access
* to a member variable.
*
* If Shape::parent were an accessor function returning a Return<Shape*>, this
* could not happen: Return ensures either immediate rooting or no GC within
* the same expression.
*/
template <typename T>
class Return
{
friend class Rooted<T>;
const T ptr_;
public:
template <typename S>
Return(const S &ptr,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
: ptr_(ptr)
{}
Return(NullPtr) : ptr_(NULL) {}
/*
* |get(AutoAssertNoGC &)| is the safest way to access a Return<T> without
* rooting it first: it is impossible to call this method without an
* AutoAssertNoGC in scope, so the compiler will automatically catch any
* incorrect usage.
*
* Example:
* AutoAssertNoGC nogc;
* RawScript script = fun->script().get(nogc);
*/
const T &get(AutoAssertNoGC &) const {
return ptr_;
}
/*
* |operator->|'s result cannot be stored in a local variable, so it is safe
* to use in a CanGC context iff no GC can occur anywhere within the same
* expression (generally from one |;| to the next). |operator->| uses a
* temporary object as a guard and will assert if a CanGC context is
* encountered before the next C++ Sequence Point.
*
* INCORRECT:
* fun->script()->bindings = myBindings->clone(cx, ...);
*
* The compiler is allowed to reorder |fun->script()::operator->()| above
* the call to |clone(cx, ...)|. In this case, the RawScript C++ stores on
* the stack may be corrupted by a GC under |clone|. The subsequent
* dereference of this pointer to get |bindings| will result in an invalid
* access. This wrapper ensures that such usage asserts in DEBUG builds when
* it encounters this situation. Without this assertion, it is possible for
* such access to corrupt program state instead of crashing immediately.
*
* CORRECT:
* RootedScript clone(cx, myBindings->clone(cx, ...));
* fun->script()->bindings = clone;
*/
#ifdef DEBUG
IntermediateNoGC<T> operator->() const {
return IntermediateNoGC<T>(ptr_);
}
#else
const T &operator->() const {
return ptr_;
}
#endif
/*
* |unsafeGet()| is unsafe for most uses. Although it performs similar
* checking to |operator->|, its result can be stored to a local variable.
* For this reason, it should only be used when it would be incorrect or
* absurd to create a new Rooted for its use: e.g. for assertions.
*/
#ifdef DEBUG
IntermediateNoGC<T> unsafeGet() const {
return IntermediateNoGC<T>(ptr_);
}
#else
const T &unsafeGet() const {
return ptr_;
}
#endif
/*
* |operator==| is safe to use in any context. It is present to allow:
* JS_ASSERT(myScript == fun->script().unsafeGet());
*
* To be rewritten as:
* JS_ASSERT(fun->script() == myScript);
*
* Note: the new order tells C++ to use |Return<JSScript*>::operator=|
* instead of direct pointer comparison.
*/
bool operator==(const T &other) { return ptr_ == other; }
bool operator!=(const T &other) { return ptr_ != other; }
bool operator==(const Return<T> &other) { return ptr_ == other.ptr_; }
bool operator==(const JS::Handle<T> &other) { return ptr_ == other.get(); }
inline bool operator==(const Rooted<T> &other);
};
/*
* By default, pointers should use the inheritance hierarchy to find their
* ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
@ -332,12 +501,6 @@ struct RootMethods<T *>
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
};
#if !(defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING))
// Defined in vm/String.h.
template <>
class Rooted<JSStableString *>;
#endif
template <typename T>
class RootedBase {};
@ -356,27 +519,23 @@ class Rooted : public RootedBase<T>
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ContextFriendFields *cx = ContextFriendFields::get(cxArg);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
commonInit(cx->thingGCRooters);
#endif
}
void init(JSRuntime *rtArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
RuntimeFriendFields *rt = const_cast<RuntimeFriendFields *>(RuntimeFriendFields::get(rtArg));
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::getMainThread(rtArg);
commonInit(pt->thingGCRooters);
#endif
}
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&rt->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
void init(js::PerThreadData *ptArg)
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
PerThreadDataFriendFields *pt = PerThreadDataFriendFields::get(ptArg);
commonInit(pt->thingGCRooters);
#endif
}
@ -413,6 +572,40 @@ class Rooted : public RootedBase<T>
init(cx);
}
Rooted(js::PerThreadData *pt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(RootMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
Rooted(js::PerThreadData *pt, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
template <typename S>
Rooted(JSContext *cx, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial.ptr_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(cx);
}
template <typename S>
Rooted(js::PerThreadData *pt, const Return<S> &initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial.ptr_)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
init(pt);
}
~Rooted()
{
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
@ -445,7 +638,25 @@ class Rooted : public RootedBase<T>
return ptr;
}
template <typename S>
T & operator =(const Return<S> &value)
{
ptr = value.ptr_;
return ptr;
}
private:
void commonInit(Rooted<void*> **thingGCRooters) {
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Rooted<T>**>(&thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
#endif
}
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
Rooted<T> **stack, *prev;
#endif
@ -455,6 +666,19 @@ class Rooted : public RootedBase<T>
Rooted(const Rooted &) MOZ_DELETE;
};
#if !(defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING))
// Defined in vm/String.h.
template <>
class Rooted<JSStableString *>;
#endif
template <typename T>
bool
Return<T>::operator==(const Rooted<T> &other)
{
return ptr_ == other.get();
}
typedef Rooted<JSObject*> RootedObject;
typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSScript*> RootedScript;
@ -550,10 +774,6 @@ MutableHandle<T>::MutableHandle(js::Rooted<S> *root,
ptr = root->address();
}
JS_FRIEND_API(void) EnterAssertNoGCScope();
JS_FRIEND_API(void) LeaveAssertNoGCScope();
JS_FRIEND_API(bool) InNoGCScope();
/*
* The scoped guard object AutoAssertNoGC forces the GC to assert if a GC is
* attempted while the guard object is live. If you have a GC-unsafe operation
@ -581,15 +801,11 @@ public:
/*
* AssertCanGC will assert if it is called inside of an AutoAssertNoGC region.
*/
#ifdef DEBUG
JS_ALWAYS_INLINE void
AssertCanGC()
{
JS_ASSERT(!InNoGCScope());
}
#else
# define AssertCanGC()
#endif
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
extern void

View File

@ -1,193 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jsgc_statistics_h___
#define jsgc_statistics_h___
#include <string.h>
#include "jsfriendapi.h"
#include "jspubtd.h"
#include "jsutil.h"
struct JSCompartment;
namespace js {
namespace gcstats {
enum Phase {
PHASE_GC_BEGIN,
PHASE_WAIT_BACKGROUND_THREAD,
PHASE_PURGE,
PHASE_MARK,
PHASE_MARK_DISCARD_CODE,
PHASE_MARK_ROOTS,
PHASE_MARK_TYPES,
PHASE_MARK_DELAYED,
PHASE_MARK_WEAK,
PHASE_MARK_GRAY,
PHASE_MARK_GRAY_WEAK,
PHASE_FINALIZE_START,
PHASE_SWEEP,
PHASE_SWEEP_ATOMS,
PHASE_SWEEP_COMPARTMENTS,
PHASE_SWEEP_TABLES,
PHASE_SWEEP_OBJECT,
PHASE_SWEEP_STRING,
PHASE_SWEEP_SCRIPT,
PHASE_SWEEP_SHAPE,
PHASE_SWEEP_IONCODE,
PHASE_SWEEP_DISCARD_CODE,
PHASE_DISCARD_ANALYSIS,
PHASE_DISCARD_TI,
PHASE_FREE_TI_ARENA,
PHASE_SWEEP_TYPES,
PHASE_CLEAR_SCRIPT_ANALYSIS,
PHASE_FINALIZE_END,
PHASE_DESTROY,
PHASE_GC_END,
PHASE_LIMIT
};
enum Stat {
STAT_NEW_CHUNK,
STAT_DESTROY_CHUNK,
STAT_LIMIT
};
class StatisticsSerializer;
struct Statistics {
Statistics(JSRuntime *rt);
~Statistics();
void beginPhase(Phase phase);
void endPhase(Phase phase);
void beginSlice(int collectedCount, int compartmentCount, gcreason::Reason reason);
void endSlice();
void reset(const char *reason) { slices.back().resetReason = reason; }
void nonincremental(const char *reason) { nonincrementalReason = reason; }
void count(Stat s) {
JS_ASSERT(s < STAT_LIMIT);
counts[s]++;
}
int64_t beginSCC();
void endSCC(unsigned scc, int64_t start);
jschar *formatMessage();
jschar *formatJSON(uint64_t timestamp);
private:
JSRuntime *runtime;
int64_t startupTime;
FILE *fp;
bool fullFormat;
/*
* GCs can't really nest, but a second GC can be triggered from within the
* JSGC_END callback.
*/
int gcDepth;
int collectedCount;
int compartmentCount;
const char *nonincrementalReason;
struct SliceData {
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
{
PodArrayZero(phaseTimes);
}
gcreason::Reason reason;
const char *resetReason;
int64_t start, end;
size_t startFaults, endFaults;
int64_t phaseTimes[PHASE_LIMIT];
int64_t duration() const { return end - start; }
};
Vector<SliceData, 8, SystemAllocPolicy> slices;
/* Most recent time when the given phase started. */
int64_t phaseStartTimes[PHASE_LIMIT];
/* Total time in a given phase for this GC. */
int64_t phaseTimes[PHASE_LIMIT];
/* Total time in a given phase over all GCs. */
int64_t phaseTotals[PHASE_LIMIT];
/* Number of events of this type for this GC. */
unsigned int counts[STAT_LIMIT];
/* Allocated space before the GC started. */
size_t preBytes;
/* Sweep times for SCCs of compartments. */
Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
void beginGC();
void endGC();
void gcDuration(int64_t *total, int64_t *maxPause);
void sccDurations(int64_t *total, int64_t *maxPause);
void printStats();
bool formatData(StatisticsSerializer &ss, uint64_t timestamp);
double computeMMU(int64_t resolution);
};
struct AutoGCSlice {
AutoGCSlice(Statistics &stats, int collectedCount, int compartmentCount, gcreason::Reason reason
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
stats.beginSlice(collectedCount, compartmentCount, reason);
}
~AutoGCSlice() { stats.endSlice(); }
Statistics &stats;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoPhase {
AutoPhase(Statistics &stats, Phase phase JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats), phase(phase) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginPhase(phase); }
~AutoPhase() { stats.endPhase(phase); }
Statistics &stats;
Phase phase;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoSCC {
AutoSCC(Statistics &stats, unsigned scc JS_GUARD_OBJECT_NOTIFIER_PARAM)
: stats(stats), scc(scc) { JS_GUARD_OBJECT_NOTIFIER_INIT; start = stats.beginSCC(); }
~AutoSCC() { stats.endSCC(scc, start); }
Statistics &stats;
unsigned scc;
int64_t start;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
} /* namespace gcstats */
} /* namespace js */
#endif /* jsgc_statistics_h___ */

View File

@ -1,398 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef JSGC_GENERATIONAL
#ifndef jsgc_storebuffer_h___
#define jsgc_storebuffer_h___
#include "jsgc.h"
#include "jsalloc.h"
#include "gc/Marking.h"
namespace js {
namespace gc {
/*
* Note: this is a stub Nursery that does not actually contain a heap, just a
* set of pointers which are "inside" the nursery to implement verification.
*/
class Nursery
{
HashSet<void*, PointerHasher<void*, 3>, SystemAllocPolicy> nursery;
public:
Nursery() : nursery() {}
bool enable() {
if (!nursery.initialized())
return nursery.init();
return true;
}
void disable() {
if (!nursery.initialized())
return;
nursery.finish();
}
bool isInside(void *cell) const {
JS_ASSERT((uintptr_t(cell) & 0x3) == 0);
return nursery.initialized() && nursery.has(cell);
}
void insertPointer(void *cell) {
nursery.putNew(cell);
}
};
/*
* BufferableRef represents an abstract reference for use in the generational
* GC's remembered set. Entries in the store buffer that cannot be represented
* with the simple pointer-to-a-pointer scheme must derive from this class and
* use the generic store buffer interface.
*/
class BufferableRef
{
public:
virtual bool match(void *location) = 0;
virtual void mark(JSTracer *trc) = 0;
};
/*
* HashKeyRef represents a reference to a HashTable key. Manual HashTable
* barriers should should instantiate this template with their own table/key
* type to insert into the generic buffer with putGeneric.
*/
template <typename Map, typename Key>
class HashKeyRef : public BufferableRef
{
Map *map;
Key key;
typedef typename Map::Ptr Ptr;
public:
HashKeyRef(Map *m, const Key &k) : map(m), key(k) {}
bool match(void *location) {
Ptr p = map->lookup(key);
if (!p)
return false;
return &p->key == location;
}
void mark(JSTracer *trc) {}
};
/*
* The StoreBuffer observes all writes that occur in the system and performs
* efficient filtering of them to derive a remembered set for nursery GC.
*/
class StoreBuffer
{
/* TODO: profile to find the ideal size for these. */
static const size_t ValueBufferSize = 1 * 1024 * sizeof(Value *);
static const size_t CellBufferSize = 2 * 1024 * sizeof(Cell **);
static const size_t SlotBufferSize = 2 * 1024 * (sizeof(JSObject *) + sizeof(uint32_t));
static const size_t RelocValueBufferSize = 1 * 1024 * sizeof(Value *);
static const size_t RelocCellBufferSize = 1 * 1024 * sizeof(Cell **);
static const size_t GenericBufferSize = 1 * 1024 * sizeof(int);
static const size_t TotalSize = ValueBufferSize + CellBufferSize +
SlotBufferSize + RelocValueBufferSize + RelocCellBufferSize +
GenericBufferSize;
typedef HashSet<void *, PointerHasher<void *, 3>, SystemAllocPolicy> EdgeSet;
/*
* This buffer holds only a single type of edge. Using this buffer is more
* efficient than the generic buffer when many writes will be to the same
* type of edge: e.g. Value or Cell*.
*/
template<typename T>
class MonoTypeBuffer
{
friend class StoreBuffer;
StoreBuffer *owner;
Nursery *nursery;
T *base; /* Pointer to the start of the buffer. */
T *pos; /* Pointer to the current insertion position. */
T *top; /* Pointer to one element after the end. */
MonoTypeBuffer(StoreBuffer *owner, Nursery *nursery)
: owner(owner), nursery(nursery), base(NULL), pos(NULL), top(NULL)
{}
MonoTypeBuffer &operator=(const MonoTypeBuffer& other) MOZ_DELETE;
bool enable(uint8_t *region, size_t len);
void disable();
bool isEmpty() const { return pos == base; }
bool isFull() const { JS_ASSERT(pos <= top); return pos == top; }
/* Compaction algorithms. */
void compactNotInSet();
/*
* Attempts to reduce the usage of the buffer by removing unnecessary
* entries.
*/
virtual void compact();
/* Add one item to the buffer. */
void put(const T &v);
/* For verification. */
bool accumulateEdges(EdgeSet &edges);
};
/*
* Overrides the MonoTypeBuffer to support pointers that may be moved in
* memory outside of the GC's control.
*/
template <typename T>
class RelocatableMonoTypeBuffer : public MonoTypeBuffer<T>
{
friend class StoreBuffer;
RelocatableMonoTypeBuffer(StoreBuffer *owner, Nursery *nursery)
: MonoTypeBuffer<T>(owner, nursery)
{}
/* Override compaction to filter out removed items. */
void compactMoved();
virtual void compact();
/* Record a removal from the buffer. */
void unput(const T &v);
};
class GenericBuffer
{
friend class StoreBuffer;
StoreBuffer *owner;
Nursery *nursery;
uint8_t *base; /* Pointer to start of buffer. */
uint8_t *pos; /* Pointer to current buffer position. */
uint8_t *top; /* Pointer to one past the last entry. */
GenericBuffer(StoreBuffer *owner, Nursery *nursery)
: owner(owner), nursery(nursery)
{}
GenericBuffer &operator=(const GenericBuffer& other) MOZ_DELETE;
bool enable(uint8_t *region, size_t len);
void disable();
/* Check if a pointer is present in the buffer. */
bool containsEdge(void *location) const;
template <typename T>
void put(const T &t) {
/* Check if we have been enabled. */
if (!pos)
return;
/* Check for overflow. */
if (top - pos < (unsigned)(sizeof(unsigned) + sizeof(T))) {
owner->setOverflowed();
return;
}
*((unsigned *)pos) = sizeof(T);
pos += sizeof(unsigned);
T *p = (T *)pos;
new (p) T(t);
pos += sizeof(T);
}
};
class CellPtrEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<CellPtrEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<CellPtrEdge>;
Cell **edge;
CellPtrEdge(Cell **v) : edge(v) {}
bool operator==(const CellPtrEdge &other) const { return edge == other.edge; }
bool operator!=(const CellPtrEdge &other) const { return edge != other.edge; }
void *location() const { return (void *)edge; }
bool inRememberedSet(Nursery *n) {
return !n->isInside(edge) && n->isInside(*edge);
}
bool isNullEdge() const {
return !*edge;
}
CellPtrEdge tagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) | 1)); }
CellPtrEdge untagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) & ~1)); }
bool isTagged() const { return bool(uintptr_t(edge) & 1); }
};
class ValueEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<ValueEdge>;
friend class StoreBuffer::RelocatableMonoTypeBuffer<ValueEdge>;
Value *edge;
ValueEdge(Value *v) : edge(v) {}
bool operator==(const ValueEdge &other) const { return edge == other.edge; }
bool operator!=(const ValueEdge &other) const { return edge != other.edge; }
void *deref() const { return edge->isGCThing() ? edge->toGCThing() : NULL; }
void *location() const { return (void *)edge; }
bool inRememberedSet(Nursery *n) {
return !n->isInside(edge) && n->isInside(deref());
}
bool isNullEdge() const {
return !deref();
}
ValueEdge tagged() const { return ValueEdge((Value *)(uintptr_t(edge) | 1)); }
ValueEdge untagged() const { return ValueEdge((Value *)(uintptr_t(edge) & ~1)); }
bool isTagged() const { return bool(uintptr_t(edge) & 1); }
};
struct SlotEdge
{
friend class StoreBuffer;
friend class StoreBuffer::MonoTypeBuffer<SlotEdge>;
JSObject *object;
uint32_t offset;
SlotEdge(JSObject *object, uint32_t offset) : object(object), offset(offset) {}
bool operator==(const SlotEdge &other) const {
return object == other.object && offset == other.offset;
}
bool operator!=(const SlotEdge &other) const {
return object != other.object || offset != other.offset;
}
HeapSlot *slotLocation() const {
if (object->isDenseArray()) {
if (offset >= object->getDenseArrayInitializedLength())
return NULL;
return (HeapSlot *)&object->getDenseArrayElement(offset);
}
if (offset >= object->slotSpan())
return NULL;
return &object->getSlotRef(offset);
}
void *deref() const {
HeapSlot *loc = slotLocation();
return (loc && loc->isGCThing()) ? loc->toGCThing() : NULL;
}
void *location() const {
return (void *)slotLocation();
}
bool inRememberedSet(Nursery *n) {
return !n->isInside(object) && n->isInside(deref());
}
bool isNullEdge() const {
return !deref();
}
};
MonoTypeBuffer<ValueEdge> bufferVal;
MonoTypeBuffer<CellPtrEdge> bufferCell;
MonoTypeBuffer<SlotEdge> bufferSlot;
RelocatableMonoTypeBuffer<ValueEdge> bufferRelocVal;
RelocatableMonoTypeBuffer<CellPtrEdge> bufferRelocCell;
GenericBuffer bufferGeneric;
Nursery *nursery;
void *buffer;
bool overflowed;
bool enabled;
/* For the verifier. */
EdgeSet edgeSet;
/* For use by our owned buffers. */
void setOverflowed() { overflowed = true; }
public:
StoreBuffer(Nursery *n)
: bufferVal(this, n), bufferCell(this, n), bufferSlot(this, n),
bufferRelocVal(this, n), bufferRelocCell(this, n), bufferGeneric(this, n),
nursery(n), buffer(NULL), overflowed(false), enabled(false)
{}
bool enable();
void disable();
bool isEnabled() { return enabled; }
/* Get the overflowed status. */
bool hasOverflowed() const { return overflowed; }
/* Insert a single edge into the buffer/remembered set. */
void putValue(Value *v) {
bufferVal.put(v);
}
void putCell(Cell **o) {
bufferCell.put(o);
}
void putSlot(JSObject *obj, uint32_t slot) {
bufferSlot.put(SlotEdge(obj, slot));
}
/* Insert or update a single edge in the Relocatable buffer. */
void putRelocatableValue(Value *v) {
bufferRelocVal.put(v);
}
void putRelocatableCell(Cell **c) {
bufferRelocCell.put(c);
}
void removeRelocatableValue(Value *v) {
bufferRelocVal.unput(v);
}
void removeRelocatableCell(Cell **c) {
bufferRelocCell.unput(c);
}
/* Insert an entry into the generic buffer. */
template <typename T>
void putGeneric(const T &t) {
bufferGeneric.put(t);
}
/* For the verifier. */
bool coalesceForVerification();
void releaseVerificationData();
bool containsEdgeAt(void *loc) const;
};
} /* namespace gc */
} /* namespace js */
#endif /* jsgc_storebuffer_h___ */
#endif /* JSGC_GENERATIONAL */

View File

@ -60,7 +60,7 @@
/* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being
correct. */
#define JS_METHODJIT 1
/* #undef JS_METHODJIT */
/* Define to 1 to enable support for E4X (ECMA-357), 0 to disable it. */
#define JS_HAS_XML_SUPPORT 1

View File

@ -375,3 +375,5 @@ MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 321, 0, JSEXN_TYPEERR, "proxy must report
MSG_DEF(JSMSG_CANT_SET_NW_NC, 322, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property")
MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 323, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter")
MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 324, 2, JSEXN_TYPEERR, "{0} does not refer to {1}")
MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY, 325, 2, JSEXN_TYPEERR, "{0} is a wrapper around {1}, but a direct reference is required")
MSG_DEF(JSMSG_UNWRAP_DENIED, 326, 0, JSEXN_ERR, "permission denied to unwrap object")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_heap_api_h___
#define js_heap_api_h___
/* These values are private to the JS engine. */
namespace js {
namespace gc {
/*
* Page size must be static to support our arena pointer optimizations, so we
* are forced to support each platform with non-4096 pages as a special case.
* Note: The freelist supports a maximum arena shift of 15.
* Note: Do not use JS_CPU_SPARC here, this header is used outside JS.
*/
#if (defined(SOLARIS) || defined(__FreeBSD__)) && \
(defined(__sparc) || defined(__sparcv9) || defined(__ia64))
const size_t PageShift = 13;
const size_t ArenaShift = PageShift;
#elif defined(__powerpc64__)
const size_t PageShift = 16;
const size_t ArenaShift = 12;
#else
const size_t PageShift = 12;
const size_t ArenaShift = PageShift;
#endif
const size_t PageSize = size_t(1) << PageShift;
const size_t ArenaSize = size_t(1) << ArenaShift;
const size_t ArenaMask = ArenaSize - 1;
const size_t ChunkShift = 20;
const size_t ChunkSize = size_t(1) << ChunkShift;
const size_t ChunkMask = ChunkSize - 1;
} /* namespace gc */
} /* namespace js */
namespace JS {
namespace shadow {
struct ArenaHeader
{
JSCompartment *compartment;
};
} /* namespace shadow */
static inline shadow::ArenaHeader *
GetGCThingArena(void *thing)
{
uintptr_t addr = uintptr_t(thing);
addr &= ~js::gc::ArenaMask;
return reinterpret_cast<shadow::ArenaHeader *>(addr);
}
static inline JSCompartment *
GetGCThingCompartment(void *thing)
{
JS_ASSERT(thing);
return GetGCThingArena(thing)->compartment;
}
static inline JSCompartment *
GetObjectCompartment(JSObject *obj)
{
return GetGCThingCompartment(obj);
}
} /* namespace JS */
#endif /* js_heap_api_h___ */

View File

@ -38,22 +38,37 @@ namespace JS {
struct TypeInferenceSizes
{
TypeInferenceSizes()
: scripts(0)
, objects(0)
, tables(0)
, temporary(0)
: typeScripts(0)
, typeResults(0)
, analysisPool(0)
, typePool(0)
, pendingArrays(0)
, allocationSiteTables(0)
, arrayTypeTables(0)
, objectTypeTables(0)
, typeObjects(0)
{}
size_t scripts;
size_t objects;
size_t tables;
size_t temporary;
size_t typeScripts;
size_t typeResults;
size_t analysisPool;
size_t typePool;
size_t pendingArrays;
size_t allocationSiteTables;
size_t arrayTypeTables;
size_t objectTypeTables;
size_t typeObjects;
void add(TypeInferenceSizes &sizes) {
this->scripts += sizes.scripts;
this->objects += sizes.objects;
this->tables += sizes.tables;
this->temporary += sizes.temporary;
this->typeScripts += sizes.typeScripts;
this->typeResults += sizes.typeResults;
this->analysisPool += sizes.analysisPool;
this->typePool += sizes.typePool;
this->pendingArrays += sizes.pendingArrays;
this->allocationSiteTables += sizes.allocationSiteTables;
this->arrayTypeTables += sizes.arrayTypeTables;
this->objectTypeTables += sizes.objectTypeTables;
this->typeObjects += sizes.typeObjects;
}
};
@ -129,10 +144,15 @@ struct CompartmentStats
, extra2(0)
, gcHeapArenaAdmin(0)
, gcHeapUnusedGcThings(0)
, gcHeapObjectsNonFunction(0)
, gcHeapObjectsOrdinary(0)
, gcHeapObjectsFunction(0)
, gcHeapStrings(0)
, gcHeapShapesTree(0)
, gcHeapObjectsDenseArray(0)
, gcHeapObjectsSlowArray(0)
, gcHeapObjectsCrossCompartmentWrapper(0)
, gcHeapStringsNormal(0)
, gcHeapStringsShort(0)
, gcHeapShapesTreeGlobalParented(0)
, gcHeapShapesTreeNonGlobalParented(0)
, gcHeapShapesDict(0)
, gcHeapShapesBase(0)
, gcHeapScripts(0)
@ -147,7 +167,7 @@ struct CompartmentStats
, objectsExtraRegExpStatics(0)
, objectsExtraPropertyIteratorData(0)
, objectsExtraPrivate(0)
, nonHugeStringChars(0)
, stringCharsNonHuge(0)
, shapesExtraTreeTables(0)
, shapesExtraDictTables(0)
, shapesExtraTreeShapeKids(0)
@ -156,7 +176,7 @@ struct CompartmentStats
, jaegerData(0)
, ionData(0)
, compartmentObject(0)
, crossCompartmentWrappers(0)
, crossCompartmentWrappersTable(0)
, regexpCompartment(0)
, debuggeesSet(0)
{}
@ -166,10 +186,15 @@ struct CompartmentStats
, extra2(other.extra2)
, gcHeapArenaAdmin(other.gcHeapArenaAdmin)
, gcHeapUnusedGcThings(other.gcHeapUnusedGcThings)
, gcHeapObjectsNonFunction(other.gcHeapObjectsNonFunction)
, gcHeapObjectsOrdinary(other.gcHeapObjectsOrdinary)
, gcHeapObjectsFunction(other.gcHeapObjectsFunction)
, gcHeapStrings(other.gcHeapStrings)
, gcHeapShapesTree(other.gcHeapShapesTree)
, gcHeapObjectsDenseArray(other.gcHeapObjectsDenseArray)
, gcHeapObjectsSlowArray(other.gcHeapObjectsSlowArray)
, gcHeapObjectsCrossCompartmentWrapper(other.gcHeapObjectsCrossCompartmentWrapper)
, gcHeapStringsNormal(other.gcHeapStringsNormal)
, gcHeapStringsShort(other.gcHeapStringsShort)
, gcHeapShapesTreeGlobalParented(other.gcHeapShapesTreeGlobalParented)
, gcHeapShapesTreeNonGlobalParented(other.gcHeapShapesTreeNonGlobalParented)
, gcHeapShapesDict(other.gcHeapShapesDict)
, gcHeapShapesBase(other.gcHeapShapesBase)
, gcHeapScripts(other.gcHeapScripts)
@ -184,7 +209,7 @@ struct CompartmentStats
, objectsExtraRegExpStatics(other.objectsExtraRegExpStatics)
, objectsExtraPropertyIteratorData(other.objectsExtraPropertyIteratorData)
, objectsExtraPrivate(other.objectsExtraPrivate)
, nonHugeStringChars(other.nonHugeStringChars)
, stringCharsNonHuge(other.stringCharsNonHuge)
, shapesExtraTreeTables(other.shapesExtraTreeTables)
, shapesExtraDictTables(other.shapesExtraDictTables)
, shapesExtraTreeShapeKids(other.shapesExtraTreeShapeKids)
@ -193,7 +218,7 @@ struct CompartmentStats
, jaegerData(other.jaegerData)
, ionData(other.ionData)
, compartmentObject(other.compartmentObject)
, crossCompartmentWrappers(other.crossCompartmentWrappers)
, crossCompartmentWrappersTable(other.crossCompartmentWrappersTable)
, regexpCompartment(other.regexpCompartment)
, debuggeesSet(other.debuggeesSet)
, typeInferenceSizes(other.typeInferenceSizes)
@ -210,10 +235,15 @@ struct CompartmentStats
size_t gcHeapArenaAdmin;
size_t gcHeapUnusedGcThings;
size_t gcHeapObjectsNonFunction;
size_t gcHeapObjectsOrdinary;
size_t gcHeapObjectsFunction;
size_t gcHeapStrings;
size_t gcHeapShapesTree;
size_t gcHeapObjectsDenseArray;
size_t gcHeapObjectsSlowArray;
size_t gcHeapObjectsCrossCompartmentWrapper;
size_t gcHeapStringsNormal;
size_t gcHeapStringsShort;
size_t gcHeapShapesTreeGlobalParented;
size_t gcHeapShapesTreeNonGlobalParented;
size_t gcHeapShapesDict;
size_t gcHeapShapesBase;
size_t gcHeapScripts;
@ -229,7 +259,7 @@ struct CompartmentStats
size_t objectsExtraRegExpStatics;
size_t objectsExtraPropertyIteratorData;
size_t objectsExtraPrivate;
size_t nonHugeStringChars;
size_t stringCharsNonHuge;
size_t shapesExtraTreeTables;
size_t shapesExtraDictTables;
size_t shapesExtraTreeShapeKids;
@ -238,7 +268,7 @@ struct CompartmentStats
size_t jaegerData;
size_t ionData;
size_t compartmentObject;
size_t crossCompartmentWrappers;
size_t crossCompartmentWrappersTable;
size_t regexpCompartment;
size_t debuggeesSet;
@ -253,10 +283,15 @@ struct CompartmentStats
ADD(gcHeapArenaAdmin);
ADD(gcHeapUnusedGcThings);
ADD(gcHeapObjectsNonFunction);
ADD(gcHeapObjectsOrdinary);
ADD(gcHeapObjectsFunction);
ADD(gcHeapStrings);
ADD(gcHeapShapesTree);
ADD(gcHeapObjectsDenseArray);
ADD(gcHeapObjectsSlowArray);
ADD(gcHeapObjectsCrossCompartmentWrapper);
ADD(gcHeapStringsNormal);
ADD(gcHeapStringsShort);
ADD(gcHeapShapesTreeGlobalParented);
ADD(gcHeapShapesTreeNonGlobalParented);
ADD(gcHeapShapesDict);
ADD(gcHeapShapesBase);
ADD(gcHeapScripts);
@ -272,7 +307,7 @@ struct CompartmentStats
ADD(objectsExtraRegExpStatics);
ADD(objectsExtraPropertyIteratorData);
ADD(objectsExtraPrivate);
ADD(nonHugeStringChars);
ADD(stringCharsNonHuge);
ADD(shapesExtraTreeTables);
ADD(shapesExtraDictTables);
ADD(shapesExtraTreeShapeKids);
@ -281,7 +316,7 @@ struct CompartmentStats
ADD(jaegerData);
ADD(ionData);
ADD(compartmentObject);
ADD(crossCompartmentWrappers);
ADD(crossCompartmentWrappersTable);
ADD(regexpCompartment);
ADD(debuggeesSet);

View File

@ -21,7 +21,6 @@
#include "jstypes.h"
#ifdef __cplusplus
# include "js/TemplateLib.h"
# include "mozilla/Scoped.h"
@ -36,12 +35,8 @@ namespace js {
/* The private namespace is a superset of the public/shared namespaces. */
using namespace JS;
using namespace mozilla;
} /* namespace js */
#endif /* __cplusplus */
JS_BEGIN_EXTERN_C
/*
* Pattern used to overwrite freed memory. If you are accessing an object with
@ -171,6 +166,8 @@ static JS_INLINE void js_free(void* p)
}
#endif/* JS_USE_CUSTOM_ALLOCATOR */
JS_BEGIN_EXTERN_C
/*
* Replace bit-scanning code sequences with CPU-specific instructions to
* speedup calculations of ceiling/floor log2.
@ -330,6 +327,8 @@ JS_PUBLIC_API(size_t) js_FloorLog2wImpl(size_t n);
# error "NOT SUPPORTED"
#endif
JS_END_EXTERN_C
/*
* Internal function.
* Compute the log of the least power of 2 greater than or equal to n. This is
@ -371,9 +370,6 @@ JS_FLOOR_LOG2W(size_t n)
#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
#include <new>
/*
@ -903,8 +899,6 @@ inline bool IsPoisonedPtr(T *v)
}
#endif /* defined(__cplusplus) */
/*
* This is SpiderMonkey's equivalent to |nsMallocSizeOfFun|.
*/

View File

@ -242,7 +242,7 @@ class Vector : private AllocPolicy
size_t mReserved; /* Max elements of reserved or used space in this vector. */
#endif
AlignedStorage<sInlineBytes> storage;
mozilla::AlignedStorage<sInlineBytes> storage;
#ifdef DEBUG
friend class ReentrancyGuard;
@ -255,7 +255,11 @@ class Vector : private AllocPolicy
/* private accessors */
bool usingInlineStorage() const {
return mBegin == (T *)storage.addr();
return mBegin == inlineStorage();
}
T *inlineStorage() const {
return (T *)storage.addr();
}
T *beginNoCheck() const {
@ -427,7 +431,7 @@ class Vector : private AllocPolicy
internalAppendN(t, n);
}
template <class U> void infallibleAppend(const U *begin, const U *end) {
internalAppend(begin, PointerRangeSize(begin, end));
internalAppend(begin, mozilla::PointerRangeSize(begin, end));
}
template <class U> void infallibleAppend(const U *begin, size_t length) {
internalAppend(begin, length);
@ -479,6 +483,8 @@ class Vector : private AllocPolicy
* object (which must be heap-allocated) itself.
*/
size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
void swap(Vector &other);
};
/* This does the re-entrancy check plus several other sanity checks. */
@ -506,6 +512,9 @@ template <class T, size_t N, class AllocPolicy>
JS_ALWAYS_INLINE
Vector<T, N, AllocPolicy>::Vector(MoveRef<Vector> rhs)
: AllocPolicy(rhs)
#ifdef DEBUG
, entered(false)
#endif
{
mLength = rhs->mLength;
mCapacity = rhs->mCapacity;
@ -856,7 +865,7 @@ JS_ALWAYS_INLINE bool
Vector<T,N,AP>::append(const U *insBegin, const U *insEnd)
{
REENTRANCY_GUARD_ET_AL;
size_t needed = PointerRangeSize(insBegin, insEnd);
size_t needed = mozilla::PointerRangeSize(insBegin, insEnd);
if (mLength + needed > mCapacity && !growStorageBy(needed))
return false;
@ -995,6 +1004,33 @@ Vector<T,N,AP>::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
}
template <class T, size_t N, class AP>
inline void
Vector<T,N,AP>::swap(Vector &other)
{
// TODO Implement N != 0
JS_STATIC_ASSERT(N == 0);
// This only works when inline storage is always empty.
if (!usingInlineStorage() && other.usingInlineStorage()) {
other.mBegin = mBegin;
mBegin = inlineStorage();
} else if (usingInlineStorage() && !other.usingInlineStorage()) {
mBegin = other.mBegin;
other.mBegin = other.inlineStorage();
} else if (!usingInlineStorage() && !other.usingInlineStorage()) {
Swap(mBegin, other.mBegin);
} else {
// This case is a no-op, since we'd set both to use their inline storage.
}
Swap(mLength, other.mLength);
Swap(mCapacity, other.mCapacity);
#ifdef DEBUG
Swap(mReserved, other.mReserved);
#endif
}
} /* namespace js */
#ifdef _MSC_VER

View File

@ -18,6 +18,8 @@ namespace js {
* - public copy constructor, assignment, destructor
* - void *malloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *calloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *realloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* The *used* bytes of the previous buffer is passed in
@ -33,6 +35,7 @@ class SystemAllocPolicy
{
public:
void *malloc_(size_t bytes) { return js_malloc(bytes); }
void *calloc_(size_t bytes) { return js_calloc(bytes); }
void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {}
@ -71,6 +74,13 @@ class TempAllocPolicy
return p;
}
void *calloc_(size_t bytes) {
void *p = js_calloc(bytes);
if (JS_UNLIKELY(!p))
p = onOutOfMemory(NULL, bytes);
return p;
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *p2 = js_realloc(p, bytes);
if (JS_UNLIKELY(!p2))

View File

@ -1 +1 @@
4f78a759104eea6e7790c03ce0130299eeaa3968
ba4ed5550f4042bc9963d0e15cce943b9f0be17a

View File

@ -13,7 +13,6 @@
#include "jsapi.h"
#include "jsprvtd.h"
#if defined(__cplusplus)
namespace JS {
struct FrameDescription
@ -47,9 +46,6 @@ JS_FRIEND_API(void) js_DumpValue(const js::Value &val);
JS_FRIEND_API(void) js_DumpId(jsid id);
JS_FRIEND_API(void) js_DumpStackFrame(JSContext *cx, js::StackFrame *start = NULL);
# endif
#endif
JS_BEGIN_EXTERN_C
JS_FRIEND_API(void)
js_DumpBacktrace(JSContext *cx);
@ -432,6 +428,4 @@ JS_UnwrapObjectAndInnerize(JSObject *obj);
extern JS_FRIEND_API(JSBool)
js_CallContextDebugHandler(JSContext *cx);
JS_END_EXTERN_C
#endif /* jsdbgapi_h___ */

View File

@ -14,8 +14,6 @@
#include "jstypes.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C
#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
#elif defined(XP_WIN)
@ -598,6 +596,4 @@ extern JS_PUBLIC_API(void)
JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp);
#endif
JS_END_EXTERN_C
#endif /* jsdhash_h___ */

View File

@ -8,12 +8,28 @@
#define jsfriendapi_h___
#include "jsclass.h"
#include "jscpucfg.h"
#include "jspubtd.h"
#include "jsprvtd.h"
#include "js/HeapAPI.h"
#include "mozilla/GuardObjects.h"
JS_BEGIN_EXTERN_C
/*
* This macro checks if the stack pointer has exceeded a given limit. If
* |tolerance| is non-zero, it returns true only if the stack pointer has
* exceeded the limit by more than |tolerance| bytes.
*/
#if JS_STACK_GROWTH_DIRECTION > 0
# define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
((uintptr_t)(sp) < (limit)+(tolerance))
#else
# define JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, sp, tolerance) \
((uintptr_t)(sp) > (limit)-(tolerance))
#endif
#define JS_CHECK_STACK_SIZE(limit, lval) JS_CHECK_STACK_SIZE_WITH_TOLERANCE(limit, lval, 0)
extern JS_FRIEND_API(void)
JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
@ -139,8 +155,6 @@ extern JS_FRIEND_API(void)
js_DumpChars(const jschar *s, size_t n);
#endif
#ifdef __cplusplus
extern JS_FRIEND_API(bool)
JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
@ -171,12 +185,6 @@ struct JSFunctionSpecWithHelp {
extern JS_FRIEND_API(bool)
JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs);
#endif
JS_END_EXTERN_C
#ifdef __cplusplus
typedef bool (* JS_SourceHook)(JSContext *cx, JSScript *script, jschar **src, uint32_t *length);
extern JS_FRIEND_API(void)
@ -184,6 +192,8 @@ JS_SetSourceHook(JSRuntime *rt, JS_SourceHook hook);
namespace js {
extern mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
inline JSRuntime *
GetRuntime(const JSContext *cx)
{
@ -259,15 +269,34 @@ TraceWeakMaps(WeakMapTracer *trc);
extern JS_FRIEND_API(bool)
GCThingIsMarkedGray(void *thing);
extern JS_FRIEND_API(bool)
AreGCGrayBitsValid(JSRuntime *rt);
/*
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JSTRACE_SHAPE. |thing| should be non-null.
*/
extern JS_FRIEND_API(void)
UnmarkGrayGCThingRecursively(void *thing, JSGCTraceKind kind);
typedef void
(GCThingCallback)(void *closure, void *gcthing);
(*GCThingCallback)(void *closure, void *gcthing);
extern JS_FRIEND_API(void)
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback callback, void *closure);
extern JS_FRIEND_API(JSObject *)
GetWeakmapKeyDelegate(JSObject *key);
JS_FRIEND_API(JSGCTraceKind)
GCThingTraceKind(void *thing);
/*
* Invoke cellCallback on every gray JS_OBJECT in the given compartment.
*/
extern JS_FRIEND_API(void)
IterateGrayObjects(JSCompartment *compartment, GCThingCallback cellCallback, void *data);
/*
* Shadow declarations of JS internal structures, for access by inline access
* functions below. Do not use these structures in any other way. When adding
@ -527,6 +556,12 @@ GetNativeStackLimit(const JSRuntime *rt)
return RuntimeFriendFields::get(rt)->nativeStackLimit;
}
/*
* These macros report a stack overflow and run |onerror| if we are close to
* using up the C stack. The JS_CHECK_CHROME_RECURSION variant gives us a little
* extra space so that we can ensure that crucial code is able to run.
*/
#define JS_CHECK_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
@ -536,6 +571,18 @@ GetNativeStackLimit(const JSRuntime *rt)
} \
JS_END_MACRO
#define JS_CHECK_CHROME_RECURSION(cx, onerror) \
JS_BEGIN_MACRO \
int stackDummy_; \
if (!JS_CHECK_STACK_SIZE_WITH_TOLERANCE(js::GetNativeStackLimit(js::GetRuntime(cx)), \
&stackDummy_, \
1024 * sizeof(size_t))) \
{ \
js_ReportOverRecursed(cx); \
onerror; \
} \
JS_END_MACRO
JS_FRIEND_API(void)
StartPCCountProfiling(JSContext *cx);
@ -979,8 +1026,6 @@ uint32_t GetListBaseExpandoSlot();
} /* namespace js */
#endif
/* Implemented in jsdate.cpp. */
/*
@ -1017,8 +1062,6 @@ js_GetSCOffset(JSStructuredCloneWriter* writer);
/* Typed Array functions, implemented in jstypedarray.cpp */
#ifdef __cplusplus
namespace js {
namespace ArrayBufferView {
@ -1038,6 +1081,12 @@ enum ViewType {
*/
TYPE_UINT8_CLAMPED,
/*
* Type returned for a DataView. Note that there is no single element type
* in this case.
*/
TYPE_DATAVIEW,
TYPE_MAX
};
@ -1045,9 +1094,6 @@ enum ViewType {
} /* namespace js */
typedef js::ArrayBufferView::ViewType JSArrayBufferViewType;
#else
typedef uint32_t JSArrayBufferViewType;
#endif /* __cplusplus */
/*
* Create a new typed array with nelements elements.
@ -1150,41 +1196,40 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
* the various accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
JS_IsTypedArrayObject(JSObject *obj);
/*
* Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping. If this test or one of the more specific tests succeeds, then it
* is safe to call the various ArrayBufferView accessor JSAPI calls defined
* below. cx MUST be non-NULL and valid.
* below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
JS_IsArrayBufferViewObject(JSObject *obj);
/*
* Test for specific typed array types (ArrayBufferView subtypes)
*/
extern JS_FRIEND_API(JSBool)
JS_IsInt8Array(JSObject *obj, JSContext *cx);
JS_IsInt8Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint8Array(JSObject *obj, JSContext *cx);
JS_IsUint8Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint8ClampedArray(JSObject *obj, JSContext *cx);
JS_IsUint8ClampedArray(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsInt16Array(JSObject *obj, JSContext *cx);
JS_IsInt16Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint16Array(JSObject *obj, JSContext *cx);
JS_IsUint16Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsInt32Array(JSObject *obj, JSContext *cx);
JS_IsInt32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsUint32Array(JSObject *obj, JSContext *cx);
JS_IsUint32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsFloat32Array(JSObject *obj, JSContext *cx);
JS_IsFloat32Array(JSObject *obj);
extern JS_FRIEND_API(JSBool)
JS_IsFloat64Array(JSObject *obj, JSContext *cx);
JS_IsFloat64Array(JSObject *obj);
/*
* Unwrap Typed arrays all at once. Return NULL without throwing if the object
@ -1192,38 +1237,37 @@ JS_IsFloat64Array(JSObject *obj, JSContext *cx);
* success, filling both outparameters.
*/
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt8Array(JSContext *cx, JSObject *obj, uint32_t *length, int8_t **data);
JS_GetObjectAsInt8Array(JSObject *obj, uint32_t *length, int8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8Array(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsUint8Array(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint8ClampedArray(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsUint8ClampedArray(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt16Array(JSContext *cx, JSObject *obj, uint32_t *length, int16_t **data);
JS_GetObjectAsInt16Array(JSObject *obj, uint32_t *length, int16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint16Array(JSContext *cx, JSObject *obj, uint32_t *length, uint16_t **data);
JS_GetObjectAsUint16Array(JSObject *obj, uint32_t *length, uint16_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsInt32Array(JSContext *cx, JSObject *obj, uint32_t *length, int32_t **data);
JS_GetObjectAsInt32Array(JSObject *obj, uint32_t *length, int32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsUint32Array(JSContext *cx, JSObject *obj, uint32_t *length, uint32_t **data);
JS_GetObjectAsUint32Array(JSObject *obj, uint32_t *length, uint32_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat32Array(JSContext *cx, JSObject *obj, uint32_t *length, float **data);
JS_GetObjectAsFloat32Array(JSObject *obj, uint32_t *length, float **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsFloat64Array(JSContext *cx, JSObject *obj, uint32_t *length, double **data);
JS_GetObjectAsFloat64Array(JSObject *obj, uint32_t *length, double **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBufferView(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data);
extern JS_FRIEND_API(JSObject *)
JS_GetObjectAsArrayBuffer(JSContext *cx, JSObject *obj, uint32_t *length, uint8_t **data);
JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data);
/*
* Get the type of elements in a typed array.
* Get the type of elements in a typed array, or TYPE_DATAVIEW if a DataView.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* |obj| must have passed a JS_IsArrayBufferView/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is an ArrayBufferView or a
* wrapper of an ArrayBufferView, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(JSArrayBufferViewType)
JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferViewType(JSObject *obj);
/*
* Check whether obj supports the JS_GetArrayBuffer* APIs. Note that this may
@ -1232,18 +1276,17 @@ JS_GetTypedArrayType(JSObject *obj, JSContext *maybecx);
* accessor JSAPI calls defined below.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferObject(JSObject *obj, JSContext *maybecx);
JS_IsArrayBufferObject(JSObject *obj);
/*
* Return the available byte length of an array buffer.
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* ArrayBuffer, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferByteLength(JSObject *obj);
/*
* Return a pointer to an array buffer's data. The buffer is still owned by the
@ -1252,22 +1295,20 @@ JS_GetArrayBufferByteLength(JSObject *obj, JSContext *maybecx);
*
* |obj| must have passed a JS_IsArrayBufferObject test, or somehow be known
* that it would pass such a test: it is an ArrayBuffer or a wrapper of an
* ArrayBuffer, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* ArrayBuffer, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint8_t *)
JS_GetArrayBufferData(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferData(JSObject *obj);
/*
* Return the number of elements in a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
JS_GetTypedArrayLength(JSObject *obj);
/*
* Return the byte offset from the start of an array buffer to the start of a
@ -1275,22 +1316,20 @@ JS_GetTypedArrayLength(JSObject *obj, JSContext *cx);
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
JS_GetTypedArrayByteOffset(JSObject *obj);
/*
* Return the byte length of a typed array.
*
* |obj| must have passed a JS_IsTypedArrayObject/JS_Is*Array test, or somehow
* be known that it would pass such a test: it is a typed array or a wrapper of
* a typed array, and the unwrapping will succeed. If cx is NULL, then DEBUG
* builds may be unable to assert when unwrapping should be disallowed.
* a typed array, and the unwrapping will succeed.
*/
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
JS_GetTypedArrayByteLength(JSObject *obj);
/*
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
@ -1298,13 +1337,13 @@ JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
* unwrapping.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
JS_IsArrayBufferViewObject(JSObject *obj);
/*
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
*/
extern JS_FRIEND_API(uint32_t)
JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
JS_GetArrayBufferViewByteLength(JSObject *obj);
/*
* Return a pointer to the start of the data referenced by a typed array. The
@ -1313,43 +1352,48 @@ JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx);
*
* |obj| must have passed a JS_Is*Array test, or somehow be known that it would
* pass such a test: it is a typed array or a wrapper of a typed array, and the
* unwrapping will succeed. If cx is NULL, then DEBUG builds may be unable to
* assert when unwrapping should be disallowed.
* unwrapping will succeed.
*/
extern JS_FRIEND_API(int8_t *)
JS_GetInt8ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt8ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint8ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint8_t *)
JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint8ClampedArrayData(JSObject *obj);
extern JS_FRIEND_API(int16_t *)
JS_GetInt16ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt16ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint16_t *)
JS_GetUint16ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint16ArrayData(JSObject *obj);
extern JS_FRIEND_API(int32_t *)
JS_GetInt32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetInt32ArrayData(JSObject *obj);
extern JS_FRIEND_API(uint32_t *)
JS_GetUint32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetUint32ArrayData(JSObject *obj);
extern JS_FRIEND_API(float *)
JS_GetFloat32ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetFloat32ArrayData(JSObject *obj);
extern JS_FRIEND_API(double *)
JS_GetFloat64ArrayData(JSObject *obj, JSContext *maybecx);
JS_GetFloat64ArrayData(JSObject *obj);
/*
* Same as above, but for any kind of ArrayBufferView. Prefer the type-specific
* versions when possible.
*/
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *maybecx);
JS_GetArrayBufferViewData(JSObject *obj);
/*
* Check whether obj supports JS_GetDataView* APIs. Note that this may fail and
* throw an exception if a security wrapper is encountered that denies the
* operation.
* Return the ArrayBuffer underlying an ArrayBufferView. If the buffer has been
* neutered, this will still return the neutered buffer. |obj| must be an
* object that would return true for JS_IsArrayBufferViewObject().
*/
extern JS_FRIEND_API(JSObject *)
JS_GetArrayBufferViewBuffer(JSObject *obj);
/*
* Check whether obj supports JS_GetDataView* APIs.
*/
JS_FRIEND_API(JSBool)
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
JS_IsDataViewObject(JSObject *obj);
/*
* Return the byte offset of a data view into its array buffer. |obj| must be a
@ -1357,11 +1401,10 @@ JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
*
* |obj| must have passed a JS_IsDataViewObject test, or somehow be known that
* it would pass such a test: it is a data view or a wrapper of a data view,
* and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be
* unable to assert when unwrapping should be disallowed.
* and the unwrapping will succeed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
JS_GetDataViewByteOffset(JSObject *obj);
/*
* Return the byte length of a data view.
@ -1372,7 +1415,7 @@ JS_GetDataViewByteOffset(JSObject *obj, JSContext *maybecx);
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
JS_GetDataViewByteLength(JSObject *obj);
/*
* Return a pointer to the beginning of the data referenced by a DataView.
@ -1383,9 +1426,8 @@ JS_GetDataViewByteLength(JSObject *obj, JSContext *maybecx);
* unable to assert when unwrapping should be disallowed.
*/
JS_FRIEND_API(void *)
JS_GetDataViewData(JSObject *obj, JSContext *maybecx);
JS_GetDataViewData(JSObject *obj);
#ifdef __cplusplus
/*
* This struct contains metadata passed from the DOM to the JS Engine for JIT
* optimizations on DOM property accessors. Eventually, this should be made
@ -1420,15 +1462,16 @@ FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
}
/* Statically asserted in jsfun.h. */
static const unsigned JS_FUNCTION_INTERPRETED_BIT = 0x1;
static JS_ALWAYS_INLINE void
SET_JITINFO(JSFunction * func, const JSJitInfo *info)
{
js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
/* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */
JS_ASSERT(!(fun->flags & 0x4000));
JS_ASSERT(!(fun->flags & JS_FUNCTION_INTERPRETED_BIT));
fun->jitinfo = info;
}
#endif /* __cplusplus */
/*
* Engine-internal extensions of jsid. This code is here only until we
@ -1494,8 +1537,6 @@ JSID_TO_ATOM(jsid id)
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
#ifdef __cplusplus
namespace js {
static JS_ALWAYS_INLINE Value
@ -1517,8 +1558,12 @@ IdToJsval(jsid id)
return IdToValue(id);
}
extern JS_FRIEND_API(bool)
IsReadOnlyDateMethod(JS::IsAcceptableThis test, JS::NativeImpl method);
extern JS_FRIEND_API(bool)
IsTypedArrayThisCheck(JS::IsAcceptableThis test);
} /* namespace js */
#endif /* __cplusplus */
#endif /* jsfriendapi_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -38,25 +38,4 @@ typedef struct PRLock PRLock;
#endif /* JS_THREADSAFE */
namespace js {
class AutoAtomicIncrement
{
int32_t *p;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
AutoAtomicIncrement(int32_t *p JS_GUARD_OBJECT_NOTIFIER_PARAM)
: p(p) {
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_ATOMIC_INCREMENT(p);
}
~AutoAtomicIncrement() {
JS_ATOMIC_DECREMENT(p);
}
};
} /* namespace js */
#endif /* jslock_h___ */

View File

@ -38,7 +38,7 @@ enum DecodingMode { STRICT, LEGACY };
namespace js {
extern JS_FRIEND_API(JSBool)
ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, HandleValue filter,
ParseJSONWithReviver(JSContext *cx, JS::StableCharPtr chars, size_t length, HandleValue filter,
MutableHandleValue vp, DecodingMode decodingMode = STRICT);
} /* namespace js */

View File

@ -16,10 +16,9 @@
** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
** %s - string
** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
** %s - ascii string
** %hs - ucs2 string
** %c - character
** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
** %p - pointer (deals with machine dependent pointer size)
** %f - float
** %g - float
@ -28,8 +27,6 @@
#include <stdio.h>
#include <stdarg.h>
JS_BEGIN_EXTERN_C
/*
** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
** of the buffer. Returns the length of the written output, NOT including
@ -77,6 +74,4 @@ extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
extern JS_PUBLIC_API(uint32_t) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
JS_END_EXTERN_C
#endif /* jsprf_h___ */

View File

@ -60,5 +60,6 @@
macro(Set, 38, js_InitSetClass) \
macro(DataView, 39, js_InitTypedArrayClasses) \
macro(ParallelArray, 40, js_InitParallelArrayClass) \
macro(Intl, 41, js_InitIntlClass) \
#endif /* jsprototypes_h___ */

View File

@ -26,7 +26,9 @@ class JS_FRIEND_API(Wrapper);
*
* Proxy traps are grouped into fundamental and derived traps. Every proxy has
* to at least provide implementations for the fundamental traps, but the
* derived traps can be implemented in terms of the fundamental ones.
* derived traps can be implemented in terms of the fundamental ones
* BaseProxyHandler provides implementations of the derived traps in terms of
* the (pure virtual) fundamental traps.
*
* To minimize code duplication, a set of abstract proxy handler classes is
* provided, from which other handlers may inherit. These abstract classes
@ -34,9 +36,9 @@ class JS_FRIEND_API(Wrapper);
*
* BaseProxyHandler
* |
* IndirectProxyHandler
* |
* DirectProxyHandler
* |
* Wrapper
*/
/*
@ -69,20 +71,6 @@ class JS_FRIEND_API(BaseProxyHandler) {
return false;
}
/*
* The function Wrapper::wrapperHandler takes a pointer to a
* BaseProxyHandler and returns a pointer to a Wrapper if and only if the
* BaseProxyHandler is a wrapper handler (otherwise, it returns NULL).
*
* Unfortunately, we can't inherit Wrapper from BaseProxyHandler, since that
* would create a dreaded diamond, and we can't use dynamic_cast to cast
* BaseProxyHandler to Wrapper, since that would require us to compile with
* run-time type information. Hence the need for this virtual function.
*/
virtual Wrapper *toWrapper() {
return NULL;
}
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
bool set, PropertyDescriptor *desc) = 0;
@ -130,17 +118,14 @@ class JS_FRIEND_API(BaseProxyHandler) {
};
/*
* IndirectProxyHandler assumes that a target exists. Moreover, it assumes the
* target is a JSObject. Consequently, it provides default implementations for
* the fundamental traps that forward their behavior to the target. The derived
* traps, however, are inherited from BaseProxyHandler, and therefore still
* implemented in terms of the fundamental ones. This allows consumers of this
* class to define custom behavior without implementing the entire gamut of
* proxy traps.
* DirectProxyHandler includes a notion of a target object. All traps are
* reimplemented such that they forward their behavior to the target. This
* allows consumers of this class to forward to another object as transparently
* and efficiently as possible.
*/
class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
public:
explicit IndirectProxyHandler(void *family);
class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler {
public:
explicit DirectProxyHandler(void *family);
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
@ -158,11 +143,21 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
virtual bool enumerate(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc,
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, Value *vp) MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, bool strict, Value *vp) MOZ_OVERRIDE;
virtual bool keys(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc,
Value *argv, Value *rval) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
@ -182,33 +177,6 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
};
/*
* DirectProxyHandler has the same assumptions about the target as its base,
* IndirectProxyHandler. Its fundamental traps are inherited from this class,
* and therefore forward their behavior to the target. The derived traps,
* however, are overrided so that, they too, forward their behavior to the
* target. This allows consumers of this class to forward to another object as
* transparently as possible.
*/
class JS_PUBLIC_API(DirectProxyHandler) : public IndirectProxyHandler {
public:
explicit DirectProxyHandler(void *family);
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, Value *vp) MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, bool strict, Value *vp) MOZ_OVERRIDE;
virtual bool keys(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp) MOZ_OVERRIDE;
};
/* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */
class Proxy {
public:
@ -350,13 +318,12 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
JSObject *proto, JSObject *parent,
JSObject *call = NULL, JSObject *construct = NULL);
} /* namespace js */
JSObject *
RenewProxyObject(JSContext *cx, JSObject *obj, BaseProxyHandler *handler, Value priv);
JS_BEGIN_EXTERN_C
} /* namespace js */
extern JS_FRIEND_API(JSObject *)
js_InitProxyClass(JSContext *cx, JSHandleObject obj);
JS_END_EXTERN_C
#endif

View File

@ -29,8 +29,6 @@
#include "js/Vector.h"
#endif
JS_BEGIN_EXTERN_C
/*
* Convenience constants.
*/
@ -129,7 +127,7 @@ class ScriptFrameIter;
class Proxy;
class JS_FRIEND_API(BaseProxyHandler);
class JS_FRIEND_API(DirectWrapper);
class JS_FRIEND_API(Wrapper);
class JS_FRIEND_API(CrossCompartmentWrapper);
class TempAllocPolicy;
@ -379,16 +377,5 @@ typedef JSObject *
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
/*
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
*/
#ifdef JS_C_STRINGS_ARE_UTF8
# define js_CStringsAreUTF8 JS_TRUE
#else
extern JSBool js_CStringsAreUTF8;
#endif
JS_END_EXTERN_C
#endif /* jsprvtd_h___ */

View File

@ -39,6 +39,8 @@ namespace JS { class Value; }
*/
#ifdef __cplusplus
#define JS_NO_JSVAL_JSID_STRUCT_TYPES
# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
# define JS_USE_JSID_STRUCT_TYPES
# endif
@ -60,8 +62,6 @@ typedef ptrdiff_t jsid;
# define JSID_BITS(id) (id)
#endif
JS_BEGIN_EXTERN_C
#ifdef WIN32
typedef wchar_t jschar;
#else
@ -217,8 +217,6 @@ typedef JSBool JSCallOnceType;
#endif
typedef JSBool (*JSInitCallback)(void);
JS_END_EXTERN_C
#ifdef __cplusplus
namespace js {
@ -311,14 +309,6 @@ struct RuntimeFriendFields {
/* Limit pointer for checking native stack consumption. */
uintptr_t nativeStackLimit;
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
RuntimeFriendFields()
: interrupt(0),
nativeStackLimit(0) { }
@ -328,6 +318,32 @@ struct RuntimeFriendFields {
}
};
class PerThreadData;
struct PerThreadDataFriendFields
{
PerThreadDataFriendFields();
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
static PerThreadDataFriendFields *get(js::PerThreadData *pt) {
return reinterpret_cast<PerThreadDataFriendFields *>(pt);
}
static PerThreadDataFriendFields *getMainThread(JSRuntime *rt) {
// mainThread must always appear directly after |RuntimeFriendFields|.
// Tested by a JS_STATIC_ASSERT in |jsfriendapi.cpp|
return reinterpret_cast<PerThreadDataFriendFields *>(
reinterpret_cast<char*>(rt) + sizeof(RuntimeFriendFields));
}
};
} /* namespace js */
#endif /* __cplusplus */

View File

@ -46,11 +46,11 @@
**
***********************************************************************/
#define JS_EXTERN_API(type) extern MOZ_EXPORT_API(type)
#define JS_EXPORT_API(type) MOZ_EXPORT_API(type)
#define JS_EXPORT_DATA(type) MOZ_EXPORT_DATA(type)
#define JS_IMPORT_API(type) MOZ_IMPORT_API(type)
#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA(type)
#define JS_EXTERN_API(type) extern MOZ_EXPORT type
#define JS_EXPORT_API(type) MOZ_EXPORT type
#define JS_EXPORT_DATA(type) MOZ_EXPORT type
#define JS_IMPORT_API(type) MOZ_IMPORT_API type
#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA type
/*
* The linkage of JS API functions differs depending on whether the file is
@ -62,11 +62,11 @@
# define JS_PUBLIC_API(t) t
# define JS_PUBLIC_DATA(t) t
#elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
# define JS_PUBLIC_API(t) MOZ_EXPORT_API(t)
# define JS_PUBLIC_DATA(t) MOZ_EXPORT_DATA(t)
# define JS_PUBLIC_API(t) MOZ_EXPORT t
# define JS_PUBLIC_DATA(t) MOZ_EXPORT t
#else
# define JS_PUBLIC_API(t) MOZ_IMPORT_API(t)
# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA(t)
# define JS_PUBLIC_API(t) MOZ_IMPORT_API t
# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA t
#endif
#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
@ -181,8 +181,6 @@
#endif
JS_BEGIN_EXTERN_C
/************************************************************************
** TYPES: JSBool
** DESCRIPTION:
@ -282,6 +280,4 @@ typedef int JSBool;
# define JS_EXTENSION_(s) s
#endif
JS_END_EXTERN_C
#endif /* jstypes_h___ */

View File

@ -369,23 +369,23 @@ class Compressor
z_stream zs;
const unsigned char *inp;
size_t inplen;
size_t outbytes;
public:
Compressor(const unsigned char *inp, size_t inplen, unsigned char *out)
: inp(inp),
inplen(inplen)
{
JS_ASSERT(inplen > 0);
zs.opaque = NULL;
zs.next_in = (Bytef *)inp;
zs.avail_in = 0;
zs.next_out = out;
zs.avail_out = inplen;
}
enum Status {
MOREOUTPUT,
DONE,
CONTINUE,
OOM
};
Compressor(const unsigned char *inp, size_t inplen);
~Compressor();
bool init();
void setOutput(unsigned char *out, size_t outlen);
size_t outWritten() const { return outbytes; }
/* Compress some of the input. Return true if it should be called again. */
bool compressMore();
/* Finalize compression. Return the length of the compressed input. */
size_t finish();
Status compressMore();
};
/*

View File

@ -14,8 +14,6 @@
#include "js/Utility.h"
JS_BEGIN_EXTERN_C
/*
* Try to get jsvals 64-bit aligned. We could almost assert that all values are
* aligned, but MSVC and GCC occasionally break alignment.
@ -835,8 +833,6 @@ JS_CANONICALIZE_NAN(double d)
return d;
}
JS_END_EXTERN_C
#ifdef __cplusplus
static jsval_layout JSVAL_TO_IMPL(JS::Value);
static JS::Value IMPL_TO_JSVAL(jsval_layout);

Some files were not shown because too many files have changed in this diff Show More