issue #1517:[Win32]Upgrading SpiderMonkey js engine to FF 16.0.1

This commit is contained in:
James Chen 2012-10-19 11:15:23 +08:00
parent ee6e139316
commit de3376b43f
60 changed files with 4770 additions and 4257 deletions

View File

@ -85,7 +85,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\scripting\javascript\spidermonkey-win32\lib\*
</Command>
</PreLinkEvent>
<Link>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;mozjs.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libcocos2d.lib;libExtensions.lib;opengl32.lib;glew32.lib;libCocosDenshion.lib;libchipmunk.lib;mozjs.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>

View File

@ -18,8 +18,12 @@
#include "cocos2d.h"
#include "cocos2d_specifics.hpp"
// for debug socket
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include <io.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#endif
#ifdef ANDROID
#include <android/log.h>
@ -290,12 +294,12 @@ void registerDefaultClasses(JSContext* cx, JSObject* global) {
JS_DefineFunction(cx, global, "executeScript", ScriptingCore::executeScript, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "forceGC", ScriptingCore::forceGC, 0, JSPROP_READONLY | JSPROP_PERMANENT);
// these are used in the debug socket
JS_DefineFunction(cx, global, "newGlobal", jsNewGlobal, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketOpen", jsSocketOpen, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketWrite", jsSocketWrite, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketRead", jsSocketRead, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketClose", jsSocketClose, 1, JSPROP_READONLY | JSPROP_PERMANENT);
// these are used in the debug socket
JS_DefineFunction(cx, global, "newGlobal", jsNewGlobal, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketOpen", jsSocketOpen, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketWrite", jsSocketWrite, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketRead", jsSocketRead, 1, JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(cx, global, "_socketClose", jsSocketClose, 1, JSPROP_READONLY | JSPROP_PERMANENT);
}
void sc_finalize(JSFreeOp *freeOp, JSObject *obj) {
@ -348,21 +352,21 @@ void ScriptingCore::string_report(jsval val) {
JSBool ScriptingCore::evalString(const char *string, jsval *outVal, const char *filename, JSContext* cx, JSObject* global)
{
jsval rval;
if (cx == NULL)
cx = cx_;
if (global == NULL)
global = global_;
JSScript* script = JS_CompileScript(cx, global, string, strlen(string), filename, 1);
if (script) {
JSAutoCompartment ac(cx, global);
JSBool evaluatedOK = JS_ExecuteScript(cx_, global_, script, &rval);
if (JS_FALSE == evaluatedOK) {
fprintf(stderr, "(evaluatedOK == JS_FALSE)\n");
}
return evaluatedOK;
}
return false;
jsval rval;
if (cx == NULL)
cx = cx_;
if (global == NULL)
global = global_;
JSScript* script = JS_CompileScript(cx, global, string, strlen(string), filename, 1);
if (script) {
// JSAutoCompartment ac(cx, global);
JSBool evaluatedOK = JS_ExecuteScript(cx_, global_, script, &rval);
if (JS_FALSE == evaluatedOK) {
fprintf(stderr, "(evaluatedOK == JS_FALSE)\n");
}
return evaluatedOK;
}
return false;
}
void ScriptingCore::start() {
@ -414,36 +418,36 @@ void ScriptingCore::createGlobalContext() {
JSBool ScriptingCore::runScript(const char *path, JSObject* global, JSContext* cx)
{
if (!path) {
return false;
}
if (!path) {
return false;
}
cocos2d::CCFileUtils *futil = cocos2d::CCFileUtils::sharedFileUtils();
std::string rpath;
if (path[0] == '/') {
rpath = path;
} else {
rpath = futil->fullPathFromRelativePath(path);
}
if (global == NULL) {
global = global_;
}
if (cx == NULL) {
cx = cx_;
}
// this will always compile the script, we can actually check if the script
// was compiled before, because it can be in the global map
JSScript* script = JS_CompileUTF8File(cx, global, rpath.c_str());
JSBool evaluatedOK = false;
if (script) {
jsval rval;
filename_script[path] = script;
JSAutoCompartment ac(cx, global);
evaluatedOK = JS_ExecuteScript(cx, global, script, &rval);
if (JS_FALSE == evaluatedOK) {
fprintf(stderr, "(evaluatedOK == JS_FALSE)\n");
}
}
return evaluatedOK;
std::string rpath;
if (path[0] == '/') {
rpath = path;
} else {
rpath = futil->fullPathFromRelativePath(path);
}
if (global == NULL) {
global = global_;
}
if (cx == NULL) {
cx = cx_;
}
// this will always compile the script, we can actually check if the script
// was compiled before, because it can be in the global map
JSScript* script = JS_CompileUTF8File(cx, global, rpath.c_str());
JSBool evaluatedOK = false;
if (script) {
jsval rval;
filename_script[path] = script;
// JSAutoCompartment ac(cx, global);
evaluatedOK = JS_ExecuteScript(cx, global, script, &rval);
if (JS_FALSE == evaluatedOK) {
fprintf(stderr, "(evaluatedOK == JS_FALSE)\n");
}
}
return evaluatedOK;
}
ScriptingCore::~ScriptingCore()
@ -459,24 +463,24 @@ ScriptingCore::~ScriptingCore()
void ScriptingCore::reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
js_log("%s:%u:%s\n",
report->filename ? report->filename : "<no filename=\"filename\">",
(unsigned int) report->lineno,
message);
js_log("%s:%u:%s\n",
report->filename ? report->filename : "<no filename=\"filename\">",
(unsigned int) report->lineno,
message);
};
JSBool ScriptingCore::log(JSContext* cx, uint32_t argc, jsval *vp)
{
if (argc > 0) {
JSString *string = NULL;
JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &string);
if (string) {
char *cstr = JS_EncodeString(cx, string);
js_log(cstr);
}
}
return JS_TRUE;
if (argc > 0) {
JSString *string = NULL;
JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &string);
if (string) {
char *cstr = JS_EncodeString(cx, string);
js_log(cstr);
}
}
return JS_TRUE;
}
@ -496,43 +500,43 @@ void ScriptingCore::removeScriptObjectByCCObject(CCObject* pObj)
JSBool ScriptingCore::setReservedSpot(uint32_t i, JSObject *obj, jsval value) {
JS_SetReservedSlot(obj, i, value);
return JS_TRUE;
JS_SetReservedSlot(obj, i, value);
return JS_TRUE;
}
JSBool ScriptingCore::executeScript(JSContext *cx, uint32_t argc, jsval *vp)
{
if (argc >= 1) {
jsval* argv = JS_ARGV(cx, vp);
JSString* str = JS_ValueToString(cx, argv[0]);
const char* path = JS_EncodeString(cx, str);
JSBool res = false;
if (argc == 2 && argv[1].isString()) {
JSString* globalName = JSVAL_TO_STRING(argv[1]);
const char* name = JS_EncodeString(cx, globalName);
js::RootedObject* rootedGlobal = globals[name];
if (rootedGlobal) {
JS_free(cx, (void*)name);
res = ScriptingCore::getInstance()->runScript(path, rootedGlobal->get());
} else {
JS_ReportError(cx, "Invalid global object: %s", name);
return JS_FALSE;
}
} else {
JSObject* glob = JS_GetGlobalForScopeChain(cx);
res = ScriptingCore::getInstance()->runScript(path, glob);
}
JS_free(cx, (void*)path);
return res;
}
return JS_TRUE;
if (argc >= 1) {
jsval* argv = JS_ARGV(cx, vp);
JSString* str = JS_ValueToString(cx, argv[0]);
const char* path = JS_EncodeString(cx, str);
JSBool res = false;
if (argc == 2 && argv[1].isString()) {
JSString* globalName = JSVAL_TO_STRING(argv[1]);
const char* name = JS_EncodeString(cx, globalName);
js::RootedObject* rootedGlobal = globals[name];
if (rootedGlobal) {
JS_free(cx, (void*)name);
res = ScriptingCore::getInstance()->runScript(path, rootedGlobal->get());
} else {
JS_ReportError(cx, "Invalid global object: %s", name);
return JS_FALSE;
}
} else {
JSObject* glob = JS_GetGlobalForScopeChain(cx);
res = ScriptingCore::getInstance()->runScript(path, glob);
}
JS_free(cx, (void*)path);
return res;
}
return JS_TRUE;
}
JSBool ScriptingCore::forceGC(JSContext *cx, uint32_t argc, jsval *vp)
{
JSRuntime *rt = JS_GetRuntime(cx);
JS_GC(rt);
return JS_TRUE;
JSRuntime *rt = JS_GetRuntime(cx);
JS_GC(rt);
return JS_TRUE;
}
static void dumpNamedRoot(const char *name, void *addr, JSGCRootType type, void *data)
@ -926,27 +930,27 @@ ccColor3B jsval_to_cccolor3b(JSContext *cx, jsval v) {
}
JSBool jsval_to_ccarray_of_CCPoint(JSContext* cx, jsval v, CCPoint **points, int *numPoints) {
// Parsing sequence
JSObject *jsobj;
JSBool ok = JS_ValueToObject( cx, v, &jsobj );
if(!jsobj || !JS_IsArrayObject( cx, jsobj)) return JS_FALSE;
uint32_t len;
JS_GetArrayLength(cx, jsobj, &len);
// Parsing sequence
JSObject *jsobj;
JSBool ok = JS_ValueToObject( cx, v, &jsobj );
if(!jsobj || !JS_IsArrayObject( cx, jsobj)) return JS_FALSE;
CCPoint *array = (CCPoint*)malloc( sizeof(CCPoint) * len);
for( uint32_t i=0; i< len;i++ ) {
jsval valarg;
JS_GetElement(cx, jsobj, i, &valarg);
uint32_t len;
JS_GetArrayLength(cx, jsobj, &len);
CCPoint *array = (CCPoint*)malloc( sizeof(CCPoint) * len);
for( uint32_t i=0; i< len;i++ ) {
jsval valarg;
JS_GetElement(cx, jsobj, i, &valarg);
array[i] = jsval_to_ccpoint(cx, valarg);
}
array[i] = jsval_to_ccpoint(cx, valarg);
}
*numPoints = len;
*points = array;
return JS_TRUE;
*numPoints = len;
*points = array;
return JS_TRUE;
}
@ -1096,148 +1100,148 @@ jsval cccolor3b_to_jsval(JSContext* cx, ccColor3B& v) {
JSObject* NewGlobalObject(JSContext* cx)
{
JSObject* glob = JS_NewGlobalObject(cx, &global_class, NULL);
if (!glob) {
return NULL;
}
JSAutoCompartment ac(cx, glob);
if (!JS_InitStandardClasses(cx, glob))
return NULL;
if (!JS_InitReflect(cx, glob))
return NULL;
if (!JS_DefineDebuggerObject(cx, glob))
return NULL;
JSObject* glob = JS_NewGlobalObject(cx, &global_class, NULL);
if (!glob) {
return NULL;
}
//JSAutoCompartment ac(cx, glob);
if (!JS_InitStandardClasses(cx, glob))
return NULL;
if (!JS_InitReflect(cx, glob))
return NULL;
if (!JS_DefineDebuggerObject(cx, glob))
return NULL;
return glob;
return glob;
}
JSBool jsNewGlobal(JSContext* cx, unsigned argc, jsval* vp)
{
if (argc == 1) {
jsval *argv = JS_ARGV(cx, vp);
JSString *jsstr = JS_ValueToString(cx, argv[0]);
std::string key = JS_EncodeString(cx, jsstr);
js::RootedObject *global = globals[key];
if (!global) {
JSObject* g = NewGlobalObject(cx);
global = new js::RootedObject(cx, g);
JS_WrapObject(cx, global->address());
globals[key] = global;
// register everything on the list on this new global object
for (std::vector<sc_register_sth>::iterator it = registrationList.begin(); it != registrationList.end(); it++) {
sc_register_sth callback = *it;
callback(cx, g);
}
}
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(*global));
return JS_TRUE;
}
return JS_FALSE;
if (argc == 1) {
jsval *argv = JS_ARGV(cx, vp);
JSString *jsstr = JS_ValueToString(cx, argv[0]);
std::string key = JS_EncodeString(cx, jsstr);
js::RootedObject *global = globals[key];
if (!global) {
JSObject* g = NewGlobalObject(cx);
global = new js::RootedObject(cx, g);
JS_WrapObject(cx, global->address());
globals[key] = global;
// register everything on the list on this new global object
for (std::vector<sc_register_sth>::iterator it = registrationList.begin(); it != registrationList.end(); it++) {
sc_register_sth callback = *it;
callback(cx, g);
}
}
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(*global));
return JS_TRUE;
}
return JS_FALSE;
}
// open a socket, bind it to a port and start listening, all at once :)
JSBool jsSocketOpen(JSContext* cx, unsigned argc, jsval* vp)
{
if (argc == 2) {
jsval* argv = JS_ARGV(cx, vp);
int port = JSVAL_TO_INT(argv[0]);
JSObject* callback = JSVAL_TO_OBJECT(argv[1]);
int s;
s = ports_sockets[port];
if (!s) {
char myname[256];
struct sockaddr_in sa;
struct hostent *hp;
memset(&sa, 0, sizeof(struct sockaddr_in));
gethostname(myname, 256);
hp = gethostbyname(myname);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(port);
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
JS_ReportError(cx, "error opening socket");
return JS_FALSE;
}
int optval = 1;
if ((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) < 0) {
close(s);
JS_ReportError(cx, "error setting socket options");
return JS_FALSE;
}
if ((bind(s, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in))) < 0) {
close(s);
JS_ReportError(cx, "error binding socket");
return JS_FALSE;
}
listen(s, 1);
int clientSocket;
if ((clientSocket = accept(s, NULL, NULL)) > 0) {
ports_sockets[port] = clientSocket;
jsval fval = OBJECT_TO_JSVAL(callback);
jsval jsSocket = INT_TO_JSVAL(clientSocket);
jsval outVal;
JS_CallFunctionValue(cx, NULL, fval, 1, &jsSocket, &outVal);
}
} else {
// just call the callback with the client socket
jsval fval = OBJECT_TO_JSVAL(callback);
jsval jsSocket = INT_TO_JSVAL(s);
jsval outVal;
JS_CallFunctionValue(cx, NULL, fval, 1, &jsSocket, &outVal);
}
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(s));
}
return JS_TRUE;
if (argc == 2) {
jsval* argv = JS_ARGV(cx, vp);
int port = JSVAL_TO_INT(argv[0]);
JSObject* callback = JSVAL_TO_OBJECT(argv[1]);
int s;
s = ports_sockets[port];
if (!s) {
char myname[256];
struct sockaddr_in sa;
struct hostent *hp;
memset(&sa, 0, sizeof(struct sockaddr_in));
gethostname(myname, 256);
hp = gethostbyname(myname);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(port);
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
JS_ReportError(cx, "error opening socket");
return JS_FALSE;
}
int optval = 1;
if ((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval))) < 0) {
close(s);
JS_ReportError(cx, "error setting socket options");
return JS_FALSE;
}
if ((bind(s, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in))) < 0) {
close(s);
JS_ReportError(cx, "error binding socket");
return JS_FALSE;
}
listen(s, 1);
int clientSocket;
if ((clientSocket = accept(s, NULL, NULL)) > 0) {
ports_sockets[port] = clientSocket;
jsval fval = OBJECT_TO_JSVAL(callback);
jsval jsSocket = INT_TO_JSVAL(clientSocket);
jsval outVal;
JS_CallFunctionValue(cx, NULL, fval, 1, &jsSocket, &outVal);
}
} else {
// just call the callback with the client socket
jsval fval = OBJECT_TO_JSVAL(callback);
jsval jsSocket = INT_TO_JSVAL(s);
jsval outVal;
JS_CallFunctionValue(cx, NULL, fval, 1, &jsSocket, &outVal);
}
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(s));
}
return JS_TRUE;
}
JSBool jsSocketRead(JSContext* cx, unsigned argc, jsval* vp)
{
if (argc == 1) {
jsval* argv = JS_ARGV(cx, vp);
int s = JSVAL_TO_INT(argv[0]);
char buff[1024];
JSString* outStr = JS_NewStringCopyZ(cx, "");
size_t bytesRead;
while ((bytesRead = read(s, buff, 1024)) > 0) {
JSString* newStr = JS_NewStringCopyN(cx, buff, bytesRead);
outStr = JS_ConcatStrings(cx, outStr, newStr);
// break on new line
if (buff[bytesRead-1] == '\n') {
break;
}
}
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(outStr));
} else {
JS_SET_RVAL(cx, vp, JSVAL_NULL);
}
return JS_TRUE;
if (argc == 1) {
jsval* argv = JS_ARGV(cx, vp);
int s = JSVAL_TO_INT(argv[0]);
char buff[1024];
JSString* outStr = JS_NewStringCopyZ(cx, "");
size_t bytesRead;
while ((bytesRead = read(s, buff, 1024)) > 0) {
JSString* newStr = JS_NewStringCopyN(cx, buff, bytesRead);
outStr = JS_ConcatStrings(cx, outStr, newStr);
// break on new line
if (buff[bytesRead-1] == '\n') {
break;
}
}
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(outStr));
} else {
JS_SET_RVAL(cx, vp, JSVAL_NULL);
}
return JS_TRUE;
}
JSBool jsSocketWrite(JSContext* cx, unsigned argc, jsval* vp)
{
if (argc == 2) {
jsval* argv = JS_ARGV(cx, vp);
int s;
const char* str;
s = JSVAL_TO_INT(argv[0]);
JSString* jsstr = JS_ValueToString(cx, argv[1]);
str = JS_EncodeString(cx, jsstr);
write(s, str, strlen(str));
JS_free(cx, (void*)str);
}
return JS_TRUE;
if (argc == 2) {
jsval* argv = JS_ARGV(cx, vp);
int s;
const char* str;
s = JSVAL_TO_INT(argv[0]);
JSString* jsstr = JS_ValueToString(cx, argv[1]);
str = JS_EncodeString(cx, jsstr);
write(s, str, strlen(str));
JS_free(cx, (void*)str);
}
return JS_TRUE;
}
JSBool jsSocketClose(JSContext* cx, unsigned argc, jsval* vp)
{
if (argc == 1) {
jsval* argv = JS_ARGV(cx, vp);
int s = JSVAL_TO_INT(argv[0]);
close(s);
}
return JS_TRUE;
if (argc == 1) {
jsval* argv = JS_ARGV(cx, vp);
int s = JSVAL_TO_INT(argv[0]);
close(s);
}
return JS_TRUE;
}

View File

@ -1,42 +1,9 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey JavaScript engine.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Terrence Cole <terrence@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 BitArray_h__
#define BitArray_h__

View File

@ -1,48 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey global object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 "jscell.h"
#include "gc/Heap.h"
#include "js/HashTable.h"
/*
@ -140,12 +108,10 @@
* and jsid, respectively.
*
* One additional note: not all object writes need to be barriered. Writes to
* newly allocated objects do not need a barrier as long as the GC is not
* allowed to run in between the allocation and the write. 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, and that no GCs have taken place between the
* object allocation and the assignment.
* 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;
@ -153,31 +119,39 @@ struct JSXML;
namespace js {
template<class T, typename Unioned = uintptr_t>
class HeapPtr
class EncapsulatedPtr
{
protected:
union {
T *value;
Unioned other;
};
public:
HeapPtr() : value(NULL) {}
explicit HeapPtr(T *v) : value(v) { post(); }
explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
EncapsulatedPtr() : value(NULL) {}
explicit EncapsulatedPtr(T *v) : value(v) {}
explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
~HeapPtr() { pre(); }
/* Use this to install a ptr into a newly allocated object. */
void init(T *v) {
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
post();
}
~EncapsulatedPtr() { pre(); }
/* Use to set the pointer to NULL. */
void clear() {
pre();
value = NULL;
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. */
@ -192,30 +166,48 @@ class HeapPtr
Unioned *unsafeGetUnioned() { return &other; }
HeapPtr<T, Unioned> &operator=(T *v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
post();
return *this;
}
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
value = v.value;
post();
return *this;
}
T &operator*() const { return *value; }
T *operator->() const { return value; }
operator T*() const { return value; }
private:
protected:
void pre() { T::writeBarrierPre(value); }
void post() { T::writeBarrierPost(value, (void *)&value); }
};
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>
@ -225,6 +217,41 @@ class HeapPtr
HeapPtr<T2> &v2, T2 *val2);
};
template <class T>
class RelocatablePtr : public EncapsulatedPtr<T>
{
public:
RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
explicit RelocatablePtr(const RelocatablePtr<T> &v)
: EncapsulatedPtr<T>(v) { post(); }
~RelocatablePtr() {
this->pre();
relocate();
}
RelocatablePtr<T> &operator=(T *v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
this->value = v;
post();
return *this;
}
RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
this->pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
this->value = v.value;
post();
return *this;
}
protected:
void post() { T::writeBarrierRelocPost(this->value, (void *)&this->value); }
void relocate() { T::writeBarrierRelocated(this->value, (void *)&this->value); }
};
/*
* 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.
@ -249,7 +276,9 @@ struct Shape;
class BaseShape;
namespace types { struct TypeObject; }
typedef HeapPtr<JSAtom> HeapPtrAtom;
typedef RelocatablePtr<JSObject> RelocatablePtrObject;
typedef RelocatablePtr<JSScript> RelocatablePtrScript;
typedef HeapPtr<JSObject> HeapPtrObject;
typedef HeapPtr<JSFunction> HeapPtrFunction;
typedef HeapPtr<JSString> HeapPtrString;
@ -272,9 +301,9 @@ struct HeapPtrHasher
/* Specialized hashing policy for HeapPtrs. */
template <class T>
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
class EncapsulatedValue
class EncapsulatedValue : public ValueOperations<EncapsulatedValue>
{
protected:
Value value;
@ -292,47 +321,27 @@ class EncapsulatedValue
~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; }
bool isUndefined() const { return value.isUndefined(); }
bool isNull() const { return value.isNull(); }
bool isBoolean() const { return value.isBoolean(); }
bool isTrue() const { return value.isTrue(); }
bool isFalse() const { return value.isFalse(); }
bool isNumber() const { return value.isNumber(); }
bool isInt32() const { return value.isInt32(); }
bool isDouble() const { return value.isDouble(); }
bool isString() const { return value.isString(); }
bool isObject() const { return value.isObject(); }
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
bool isGCThing() const { return value.isGCThing(); }
bool isMarkable() const { return value.isMarkable(); }
bool toBoolean() const { return value.toBoolean(); }
double toNumber() const { return value.toNumber(); }
int32_t toInt32() const { return value.toInt32(); }
double toDouble() const { return value.toDouble(); }
JSString *toString() const { return value.toString(); }
JSObject &toObject() const { return value.toObject(); }
JSObject *toObjectOrNull() const { return value.toObjectOrNull(); }
void *toGCThing() const { return value.toGCThing(); }
JSGCTraceKind gcKind() const { return value.gcKind(); }
uint64_t asRawBits() const { return value.asRawBits(); }
#ifdef DEBUG
JSWhyMagic whyMagic() const { return value.whyMagic(); }
#endif
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
@ -357,14 +366,31 @@ class HeapValue : public EncapsulatedValue
*/
inline void set(JSCompartment *comp, const Value &v);
static inline void writeBarrierPost(const Value &v, void *addr);
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
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);
explicit 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
{
/*
@ -401,7 +427,7 @@ class HeapSlot : public EncapsulatedValue
* Run a post write barrier that encompasses multiple contiguous slots in a
* single step.
*/
static inline void
inline void
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
{
}
@ -414,6 +440,14 @@ Valueify(const EncapsulatedValue *array)
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;
@ -428,21 +462,20 @@ class HeapSlotArray
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
};
class HeapId
class EncapsulatedId
{
protected:
jsid value;
explicit EncapsulatedId() : value(JSID_VOID) {}
explicit inline EncapsulatedId(jsid id) : value(id) {}
~EncapsulatedId() {}
private:
EncapsulatedId(const EncapsulatedId &v) MOZ_DELETE;
EncapsulatedId &operator=(const EncapsulatedId &v) MOZ_DELETE;
public:
explicit HeapId() : value(JSID_VOID) {}
explicit inline HeapId(jsid id);
inline ~HeapId();
inline void init(jsid id);
inline HeapId &operator=(jsid id);
inline HeapId &operator=(const HeapId &v);
bool operator==(jsid id) const { return value == id; }
bool operator!=(jsid id) const { return value != id; }
@ -450,11 +483,37 @@ class HeapId
jsid *unsafeGet() { return &value; }
operator jsid() const { return value; }
private:
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);
HeapId(const HeapId &v) MOZ_DELETE;
};
/*
@ -488,7 +547,7 @@ class ReadBarriered
T &operator*() const { return *get(); }
T *operator->() const { return get(); }
T *unsafeGet() { return value; }
T **unsafeGet() { return &value; }
void set(T *v) { value = v; }
@ -504,6 +563,7 @@ class ReadBarrieredValue
ReadBarrieredValue(const Value &value) : value(value) {}
inline const Value &get() const;
Value *unsafeGet() { return &value; }
inline operator const Value &() const;
inline JSObject &toObject() const;
@ -511,11 +571,11 @@ class ReadBarrieredValue
namespace tl {
template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
static const bool result = true; };
template <> struct IsPostBarrieredType<HeapSlot> { static const bool result = true; };
template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
template <> struct IsPostBarrieredType<HeapId> { static const bool result = true; };
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 */

View File

@ -0,0 +1,978 @@
/* -*- 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 gc_heap_h___
#define gc_heap_h___
#include "mozilla/Attributes.h"
#include "mozilla/StandardInteger.h"
#include <stddef.h>
#include "jstypes.h"
#include "jsutil.h"
#include "ds/BitArray.h"
struct JSCompartment;
extern "C" {
struct JSRuntime;
}
namespace js {
class FreeOp;
namespace gc {
struct Arena;
struct ArenaHeader;
struct Chunk;
/*
* Live objects are marked black. How many other additional colors are available
* depends on the size of the GCThing. Objects marked gray are eligible for
* cycle collection.
*/
static const uint32_t BLACK = 0;
static const uint32_t GRAY = 1;
/* The GC allocation kinds. */
enum AllocKind {
FINALIZE_OBJECT0,
FINALIZE_OBJECT0_BACKGROUND,
FINALIZE_OBJECT2,
FINALIZE_OBJECT2_BACKGROUND,
FINALIZE_OBJECT4,
FINALIZE_OBJECT4_BACKGROUND,
FINALIZE_OBJECT8,
FINALIZE_OBJECT8_BACKGROUND,
FINALIZE_OBJECT12,
FINALIZE_OBJECT12_BACKGROUND,
FINALIZE_OBJECT16,
FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_SCRIPT,
FINALIZE_SHAPE,
FINALIZE_BASE_SHAPE,
FINALIZE_TYPE_OBJECT,
#if JS_HAS_XML_SUPPORT
FINALIZE_XML,
#endif
FINALIZE_SHORT_STRING,
FINALIZE_STRING,
FINALIZE_EXTERNAL_STRING,
FINALIZE_LAST = FINALIZE_EXTERNAL_STRING
};
static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1;
static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1;
/*
* This must be an upper bound, but we do not need the least upper bound, so
* we just exclude non-background objects.
*/
static const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OBJECT_LIMIT / 2;
/*
* A GC cell is the base class for all GC things.
*/
struct Cell
{
static const size_t CellShift = 3;
static const size_t CellSize = size_t(1) << CellShift;
static const size_t CellMask = CellSize - 1;
inline uintptr_t address() const;
inline ArenaHeader *arenaHeader() const;
inline Chunk *chunk() const;
inline AllocKind getAllocKind() const;
MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
MOZ_ALWAYS_INLINE void unmark(uint32_t color) const;
inline JSCompartment *compartment() const;
#ifdef DEBUG
inline bool isAligned() const;
#endif
};
/*
* Page size is 4096 by default, except for SPARC, where it is 8192.
* Note: Do not use JS_CPU_SPARC here, this header is used outside JS.
* Bug 692267: Move page size definition to gc/Memory.h and include it
* directly once jsgc.h is no longer an installed header.
*/
#if defined(SOLARIS) && (defined(__sparc) || defined(__sparcv9))
const size_t PageShift = 13;
#else
const size_t PageShift = 12;
#endif
const size_t PageSize = size_t(1) << PageShift;
const size_t ChunkShift = 20;
const size_t ChunkSize = size_t(1) << ChunkShift;
const size_t ChunkMask = ChunkSize - 1;
const size_t ArenaShift = PageShift;
const size_t ArenaSize = PageSize;
const size_t ArenaMask = ArenaSize - 1;
/*
* This is the maximum number of arenas we allow in the FreeCommitted state
* before we trigger a GC_SHRINK to release free arenas to the OS.
*/
const static uint32_t FreeCommittedArenasThreshold = (32 << 20) / ArenaSize;
/*
* The mark bitmap has one bit per each GC cell. For multi-cell GC things this
* wastes space but allows to avoid expensive devisions by thing's size when
* accessing the bitmap. In addition this allows to use some bits for colored
* marking during the cycle GC.
*/
const size_t ArenaCellCount = size_t(1) << (ArenaShift - Cell::CellShift);
const size_t ArenaBitmapBits = ArenaCellCount;
const size_t ArenaBitmapBytes = ArenaBitmapBits / 8;
const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD;
/*
* A FreeSpan represents a contiguous sequence of free cells in an Arena.
* |first| is the address of the first free cell in the span. |last| is the
* address of the last free cell in the span. This last cell holds a FreeSpan
* data structure for the next span unless this is the last span on the list
* of spans in the arena. For this last span |last| points to the last byte of
* the last thing in the arena and no linkage is stored there, so
* |last| == arenaStart + ArenaSize - 1. If the space at the arena end is
* fully used this last span is empty and |first| == |last + 1|.
*
* Thus |first| < |last| implies that we have either the last span with at least
* one element or that the span is not the last and contains at least 2
* elements. In both cases to allocate a thing from this span we need simply
* to increment |first| by the allocation size.
*
* |first| == |last| implies that we have a one element span that records the
* next span. So to allocate from it we need to update the span list head
* with a copy of the span stored at |last| address so the following
* allocations will use that span.
*
* |first| > |last| implies that we have an empty last span and the arena is
* fully used.
*
* Also only for the last span (|last| & 1)! = 0 as all allocation sizes are
* multiples of Cell::CellSize.
*/
struct FreeSpan
{
uintptr_t first;
uintptr_t last;
public:
FreeSpan() {}
FreeSpan(uintptr_t first, uintptr_t last)
: first(first), last(last) {
checkSpan();
}
/*
* To minimize the size of the arena header the first span is encoded
* there as offsets from the arena start.
*/
static size_t encodeOffsets(size_t firstOffset, size_t lastOffset) {
/* Check that we can pack the offsets into uint16. */
JS_STATIC_ASSERT(ArenaShift < 16);
JS_ASSERT(firstOffset <= ArenaSize);
JS_ASSERT(lastOffset < ArenaSize);
JS_ASSERT(firstOffset <= ((lastOffset + 1) & ~size_t(1)));
return firstOffset | (lastOffset << 16);
}
/*
* Encoded offsets for a full arena when its first span is the last one
* and empty.
*/
static const size_t FullArenaOffsets = ArenaSize | ((ArenaSize - 1) << 16);
static FreeSpan decodeOffsets(uintptr_t arenaAddr, size_t offsets) {
JS_ASSERT(!(arenaAddr & ArenaMask));
size_t firstOffset = offsets & 0xFFFF;
size_t lastOffset = offsets >> 16;
JS_ASSERT(firstOffset <= ArenaSize);
JS_ASSERT(lastOffset < ArenaSize);
/*
* We must not use | when calculating first as firstOffset is
* ArenaMask + 1 for the empty span.
*/
return FreeSpan(arenaAddr + firstOffset, arenaAddr | lastOffset);
}
void initAsEmpty(uintptr_t arenaAddr = 0) {
JS_ASSERT(!(arenaAddr & ArenaMask));
first = arenaAddr + ArenaSize;
last = arenaAddr | (ArenaSize - 1);
JS_ASSERT(isEmpty());
}
bool isEmpty() const {
checkSpan();
return first > last;
}
bool hasNext() const {
checkSpan();
return !(last & uintptr_t(1));
}
const FreeSpan *nextSpan() const {
JS_ASSERT(hasNext());
return reinterpret_cast<FreeSpan *>(last);
}
FreeSpan *nextSpanUnchecked(size_t thingSize) const {
#ifdef DEBUG
uintptr_t lastOffset = last & ArenaMask;
JS_ASSERT(!(lastOffset & 1));
JS_ASSERT((ArenaSize - lastOffset) % thingSize == 0);
#endif
return reinterpret_cast<FreeSpan *>(last);
}
uintptr_t arenaAddressUnchecked() const {
return last & ~ArenaMask;
}
uintptr_t arenaAddress() const {
checkSpan();
return arenaAddressUnchecked();
}
ArenaHeader *arenaHeader() const {
return reinterpret_cast<ArenaHeader *>(arenaAddress());
}
bool isSameNonEmptySpan(const FreeSpan *another) const {
JS_ASSERT(!isEmpty());
JS_ASSERT(!another->isEmpty());
return first == another->first && last == another->last;
}
bool isWithinArena(uintptr_t arenaAddr) const {
JS_ASSERT(!(arenaAddr & ArenaMask));
/* Return true for the last empty span as well. */
return arenaAddress() == arenaAddr;
}
size_t encodeAsOffsets() const {
/*
* We must use first - arenaAddress(), not first & ArenaMask as
* first == ArenaMask + 1 for an empty span.
*/
uintptr_t arenaAddr = arenaAddress();
return encodeOffsets(first - arenaAddr, last & ArenaMask);
}
/* See comments before FreeSpan for details. */
MOZ_ALWAYS_INLINE void *allocate(size_t thingSize) {
JS_ASSERT(thingSize % Cell::CellSize == 0);
checkSpan();
uintptr_t thing = first;
if (thing < last) {
/* Bump-allocate from the current span. */
first = thing + thingSize;
} else if (JS_LIKELY(thing == last)) {
/*
* Move to the next span. We use JS_LIKELY as without PGO
* compilers mis-predict == here as unlikely to succeed.
*/
*this = *reinterpret_cast<FreeSpan *>(thing);
} else {
return NULL;
}
checkSpan();
return reinterpret_cast<void *>(thing);
}
/* A version of allocate when we know that the span is not empty. */
MOZ_ALWAYS_INLINE void *infallibleAllocate(size_t thingSize) {
JS_ASSERT(thingSize % Cell::CellSize == 0);
checkSpan();
uintptr_t thing = first;
if (thing < last) {
first = thing + thingSize;
} else {
JS_ASSERT(thing == last);
*this = *reinterpret_cast<FreeSpan *>(thing);
}
checkSpan();
return reinterpret_cast<void *>(thing);
}
/*
* Allocate from a newly allocated arena. We do not move the free list
* from the arena. Rather we set the arena up as fully used during the
* initialization so to allocate we simply return the first thing in the
* arena and set the free list to point to the second.
*/
MOZ_ALWAYS_INLINE void *allocateFromNewArena(uintptr_t arenaAddr, size_t firstThingOffset,
size_t thingSize) {
JS_ASSERT(!(arenaAddr & ArenaMask));
uintptr_t thing = arenaAddr | firstThingOffset;
first = thing + thingSize;
last = arenaAddr | ArenaMask;
checkSpan();
return reinterpret_cast<void *>(thing);
}
void checkSpan() const {
#ifdef DEBUG
/* We do not allow spans at the end of the address space. */
JS_ASSERT(last != uintptr_t(-1));
JS_ASSERT(first);
JS_ASSERT(last);
JS_ASSERT(first - 1 <= last);
uintptr_t arenaAddr = arenaAddressUnchecked();
if (last & 1) {
/* The span is the last. */
JS_ASSERT((last & ArenaMask) == ArenaMask);
if (first - 1 == last) {
/* The span is last and empty. The above start != 0 check
* implies that we are not at the end of the address space.
*/
return;
}
size_t spanLength = last - first + 1;
JS_ASSERT(spanLength % Cell::CellSize == 0);
/* Start and end must belong to the same arena. */
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
return;
}
/* The span is not the last and we have more spans to follow. */
JS_ASSERT(first <= last);
size_t spanLengthWithoutOneThing = last - first;
JS_ASSERT(spanLengthWithoutOneThing % Cell::CellSize == 0);
JS_ASSERT((first & ~ArenaMask) == arenaAddr);
/*
* If there is not enough space before the arena end to allocate one
* more thing, then the span must be marked as the last one to avoid
* storing useless empty span reference.
*/
size_t beforeTail = ArenaSize - (last & ArenaMask);
JS_ASSERT(beforeTail >= sizeof(FreeSpan) + Cell::CellSize);
FreeSpan *next = reinterpret_cast<FreeSpan *>(last);
/*
* The GC things on the list of free spans come from one arena
* and the spans are linked in ascending address order with
* at least one non-free thing between spans.
*/
JS_ASSERT(last < next->first);
JS_ASSERT(arenaAddr == next->arenaAddressUnchecked());
if (next->first > next->last) {
/*
* The next span is the empty span that terminates the list for
* arenas that do not have any free things at the end.
*/
JS_ASSERT(next->first - 1 == next->last);
JS_ASSERT(arenaAddr + ArenaSize == next->first);
}
#endif
}
};
/* Every arena has a header. */
struct ArenaHeader
{
friend struct FreeLists;
JSCompartment *compartment;
/*
* ArenaHeader::next has two purposes: when unallocated, it points to the
* next available Arena's header. When allocated, it points to the next
* arena of the same size class and compartment.
*/
ArenaHeader *next;
private:
/*
* The first span of free things in the arena. We encode it as the start
* and end offsets within the arena, not as FreeSpan structure, to
* minimize the header size.
*/
size_t firstFreeSpanOffsets;
/*
* One of AllocKind constants or FINALIZE_LIMIT when the arena does not
* contain any GC things and is on the list of empty arenas in the GC
* chunk. The latter allows to quickly check if the arena is allocated
* during the conservative GC scanning without searching the arena in the
* list.
*/
size_t allocKind : 8;
/*
* When recursive marking uses too much stack the marking is delayed and
* the corresponding arenas are put into a stack using the following field
* as a linkage. To distinguish the bottom of the stack from the arenas
* not present in the stack we use an extra flag to tag arenas on the
* stack.
*
* Delayed marking is also used for arenas that we allocate into during an
* incremental GC. In this case, we intend to mark all the objects in the
* arena, and it's faster to do this marking in bulk.
*
* To minimize the ArenaHeader size we record the next delayed marking
* linkage as arenaAddress() >> ArenaShift and pack it with the allocKind
* field and hasDelayedMarking flag. We use 8 bits for the allocKind, not
* ArenaShift - 1, so the compiler can use byte-level memory instructions
* to access it.
*/
public:
size_t hasDelayedMarking : 1;
size_t allocatedDuringIncremental : 1;
size_t markOverflow : 1;
size_t nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
static void staticAsserts() {
/* We must be able to fit the allockind into uint8_t. */
JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
/*
* nextDelayedMarkingpacking assumes that ArenaShift has enough bits
* to cover allocKind and hasDelayedMarking.
*/
JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1);
}
inline uintptr_t address() const;
inline Chunk *chunk() const;
bool allocated() const {
JS_ASSERT(allocKind <= size_t(FINALIZE_LIMIT));
return allocKind < size_t(FINALIZE_LIMIT);
}
void init(JSCompartment *comp, AllocKind kind) {
JS_ASSERT(!allocated());
JS_ASSERT(!markOverflow);
JS_ASSERT(!allocatedDuringIncremental);
JS_ASSERT(!hasDelayedMarking);
compartment = comp;
JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
allocKind = size_t(kind);
/* See comments in FreeSpan::allocateFromNewArena. */
firstFreeSpanOffsets = FreeSpan::FullArenaOffsets;
}
void setAsNotAllocated() {
allocKind = size_t(FINALIZE_LIMIT);
markOverflow = 0;
allocatedDuringIncremental = 0;
hasDelayedMarking = 0;
nextDelayedMarking = 0;
}
inline uintptr_t arenaAddress() const;
inline Arena *getArena();
AllocKind getAllocKind() const {
JS_ASSERT(allocated());
return AllocKind(allocKind);
}
inline size_t getThingSize() const;
bool hasFreeThings() const {
return firstFreeSpanOffsets != FreeSpan::FullArenaOffsets;
}
inline bool isEmpty() const;
void setAsFullyUsed() {
firstFreeSpanOffsets = FreeSpan::FullArenaOffsets;
}
inline FreeSpan getFirstFreeSpan() const;
inline void setFirstFreeSpan(const FreeSpan *span);
#ifdef DEBUG
void checkSynchronizedWithFreeList() const;
#endif
inline ArenaHeader *getNextDelayedMarking() const;
inline void setNextDelayedMarking(ArenaHeader *aheader);
};
struct Arena
{
/*
* Layout of an arena:
* An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader
* descriptor followed by some pad bytes. The remainder of the arena is
* filled with the array of T things. The pad bytes ensure that the thing
* array ends exactly at the end of the arena.
*
* +-------------+-----+----+----+-----+----+
* | ArenaHeader | pad | T0 | T1 | ... | Tn |
* +-------------+-----+----+----+-----+----+
*
* <----------------------------------------> = ArenaSize bytes
* <-------------------> = first thing offset
*/
ArenaHeader aheader;
uint8_t data[ArenaSize - sizeof(ArenaHeader)];
private:
static JS_FRIEND_DATA(const uint32_t) ThingSizes[];
static JS_FRIEND_DATA(const uint32_t) FirstThingOffsets[];
public:
static void staticAsserts();
static size_t thingSize(AllocKind kind) {
return ThingSizes[kind];
}
static size_t firstThingOffset(AllocKind kind) {
return FirstThingOffsets[kind];
}
static size_t thingsPerArena(size_t thingSize) {
JS_ASSERT(thingSize % Cell::CellSize == 0);
/* We should be able to fit FreeSpan in any GC thing. */
JS_ASSERT(thingSize >= sizeof(FreeSpan));
return (ArenaSize - sizeof(ArenaHeader)) / thingSize;
}
static size_t thingsSpan(size_t thingSize) {
return thingsPerArena(thingSize) * thingSize;
}
static bool isAligned(uintptr_t thing, size_t thingSize) {
/* Things ends at the arena end. */
uintptr_t tailOffset = (ArenaSize - thing) & ArenaMask;
return tailOffset % thingSize == 0;
}
uintptr_t address() const {
return aheader.address();
}
uintptr_t thingsStart(AllocKind thingKind) {
return address() | firstThingOffset(thingKind);
}
uintptr_t thingsEnd() {
return address() + ArenaSize;
}
template <typename T>
bool finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize);
};
inline size_t
ArenaHeader::getThingSize() const
{
JS_ASSERT(allocated());
return Arena::thingSize(getAllocKind());
}
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
struct ChunkInfo
{
Chunk *next;
Chunk **prevp;
/* Free arenas are linked together with aheader.next. */
ArenaHeader *freeArenasHead;
/*
* Decommitted arenas are tracked by a bitmap in the chunk header. We use
* this offset to start our search iteration close to a decommitted arena
* that we can allocate.
*/
uint32_t lastDecommittedArenaOffset;
/* Number of free arenas, either committed or decommitted. */
uint32_t numArenasFree;
/* Number of free, committed arenas. */
uint32_t numArenasFreeCommitted;
/* Number of GC cycles this chunk has survived. */
uint32_t age;
};
/*
* Calculating ArenasPerChunk:
*
* In order to figure out how many Arenas will fit in a chunk, we need to know
* how much extra space is available after we allocate the header data. This
* is a problem because the header size depends on the number of arenas in the
* chunk. The two dependent fields are bitmap and decommittedArenas.
*
* For the mark bitmap, we know that each arena will use a fixed number of full
* bytes: ArenaBitmapBytes. The full size of the header data is this number
* multiplied by the eventual number of arenas we have in the header. We,
* conceptually, distribute this header data among the individual arenas and do
* not include it in the header. This way we do not have to worry about its
* variable size: it gets attached to the variable number we are computing.
*
* For the decommitted arena bitmap, we only have 1 bit per arena, so this
* technique will not work. Instead, we observe that we do not have enough
* header info to fill 8 full arenas: it is currently 4 on 64bit, less on
* 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas.
* This will not become 63 bytes unless we double the data required in the
* header. Therefore, we just compute the number of bytes required to track
* every possible arena and do not worry about slop bits, since there are too
* few to usefully allocate.
*
* To actually compute the number of arenas we can allocate in a chunk, we
* divide the amount of available space less the header info (not including
* the mark bitmap which is distributed into the arena size) by the size of
* the arena (with the mark bitmap bytes it uses).
*/
const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes;
const size_t ChunkDecommitBitmapBytes = ChunkSize / ArenaSize / JS_BITS_PER_BYTE;
const size_t ChunkBytesAvailable = ChunkSize - sizeof(ChunkInfo) - ChunkDecommitBitmapBytes;
const size_t ArenasPerChunk = ChunkBytesAvailable / BytesPerArenaWithHeader;
/* A chunk bitmap contains enough mark bits for all the cells in a chunk. */
struct ChunkBitmap
{
uintptr_t bitmap[ArenaBitmapWords * ArenasPerChunk];
MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color,
uintptr_t **wordp, uintptr_t *maskp);
MOZ_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) {
uintptr_t *word, mask;
getMarkWordAndMask(cell, color, &word, &mask);
return *word & mask;
}
MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell *cell, uint32_t color) {
uintptr_t *word, mask;
getMarkWordAndMask(cell, BLACK, &word, &mask);
if (*word & mask)
return false;
*word |= mask;
if (color != BLACK) {
/*
* We use getMarkWordAndMask to recalculate both mask and word as
* doing just mask << color may overflow the mask.
*/
getMarkWordAndMask(cell, color, &word, &mask);
if (*word & mask)
return false;
*word |= mask;
}
return true;
}
MOZ_ALWAYS_INLINE void unmark(const Cell *cell, uint32_t color) {
uintptr_t *word, mask;
getMarkWordAndMask(cell, color, &word, &mask);
*word &= ~mask;
}
void clear() {
PodArrayZero(bitmap);
}
uintptr_t *arenaBits(ArenaHeader *aheader) {
/*
* We assume that the part of the bitmap corresponding to the arena
* has the exact number of words so we do not need to deal with a word
* that covers bits from two arenas.
*/
JS_STATIC_ASSERT(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD);
uintptr_t *word, unused;
getMarkWordAndMask(reinterpret_cast<Cell *>(aheader->address()), BLACK, &word, &unused);
return word;
}
};
JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap));
typedef BitArray<ArenasPerChunk> PerArenaBitmap;
const size_t ChunkPadSize = ChunkSize
- (sizeof(Arena) * ArenasPerChunk)
- sizeof(ChunkBitmap)
- sizeof(PerArenaBitmap)
- sizeof(ChunkInfo);
JS_STATIC_ASSERT(ChunkPadSize < BytesPerArenaWithHeader);
/*
* Chunks contain arenas and associated data structures (mark bitmap, delayed
* marking state).
*/
struct Chunk
{
Arena arenas[ArenasPerChunk];
/* Pad to full size to ensure cache alignment of ChunkInfo. */
uint8_t padding[ChunkPadSize];
ChunkBitmap bitmap;
PerArenaBitmap decommittedArenas;
ChunkInfo info;
static Chunk *fromAddress(uintptr_t addr) {
addr &= ~ChunkMask;
return reinterpret_cast<Chunk *>(addr);
}
static bool withinArenasRange(uintptr_t addr) {
uintptr_t offset = addr & ChunkMask;
return offset < ArenasPerChunk * ArenaSize;
}
static size_t arenaIndex(uintptr_t addr) {
JS_ASSERT(withinArenasRange(addr));
return (addr & ChunkMask) >> ArenaShift;
}
uintptr_t address() const {
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
JS_ASSERT(!(addr & ChunkMask));
return addr;
}
bool unused() const {
return info.numArenasFree == ArenasPerChunk;
}
bool hasAvailableArenas() const {
return info.numArenasFree != 0;
}
inline void addToAvailableList(JSCompartment *compartment);
inline void insertToAvailableList(Chunk **insertPoint);
inline void removeFromAvailableList();
ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind);
void releaseArena(ArenaHeader *aheader);
static Chunk *allocate(JSRuntime *rt);
/* Must be called with the GC lock taken. */
static inline void release(JSRuntime *rt, Chunk *chunk);
static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead);
/* Must be called with the GC lock taken. */
inline void prepareToBeFreed(JSRuntime *rt);
/*
* Assuming that the info.prevp points to the next field of the previous
* chunk in a doubly-linked list, get that chunk.
*/
Chunk *getPrevious() {
JS_ASSERT(info.prevp);
return fromPointerToNext(info.prevp);
}
/* Get the chunk from a pointer to its info.next field. */
static Chunk *fromPointerToNext(Chunk **nextFieldPtr) {
uintptr_t addr = reinterpret_cast<uintptr_t>(nextFieldPtr);
JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next));
return reinterpret_cast<Chunk *>(addr - offsetof(Chunk, info.next));
}
private:
inline void init();
/* Search for a decommitted arena to allocate. */
unsigned findDecommittedArenaOffset();
ArenaHeader* fetchNextDecommittedArena();
public:
/* Unlink and return the freeArenasHead. */
inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt);
inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader);
};
JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize);
inline uintptr_t
Cell::address() const
{
uintptr_t addr = uintptr_t(this);
JS_ASSERT(addr % Cell::CellSize == 0);
JS_ASSERT(Chunk::withinArenasRange(addr));
return addr;
}
inline uintptr_t
ArenaHeader::address() const
{
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
JS_ASSERT(!(addr & ArenaMask));
JS_ASSERT(Chunk::withinArenasRange(addr));
return addr;
}
inline Chunk *
ArenaHeader::chunk() const
{
return Chunk::fromAddress(address());
}
inline uintptr_t
ArenaHeader::arenaAddress() const
{
return address();
}
inline Arena *
ArenaHeader::getArena()
{
return reinterpret_cast<Arena *>(arenaAddress());
}
inline bool
ArenaHeader::isEmpty() const
{
/* Arena is empty if its first span covers the whole arena. */
JS_ASSERT(allocated());
size_t firstThingOffset = Arena::firstThingOffset(getAllocKind());
return firstFreeSpanOffsets == FreeSpan::encodeOffsets(firstThingOffset, ArenaMask);
}
FreeSpan
ArenaHeader::getFirstFreeSpan() const
{
#ifdef DEBUG
checkSynchronizedWithFreeList();
#endif
return FreeSpan::decodeOffsets(arenaAddress(), firstFreeSpanOffsets);
}
void
ArenaHeader::setFirstFreeSpan(const FreeSpan *span)
{
JS_ASSERT(span->isWithinArena(arenaAddress()));
firstFreeSpanOffsets = span->encodeAsOffsets();
}
inline ArenaHeader *
ArenaHeader::getNextDelayedMarking() const
{
return &reinterpret_cast<Arena *>(nextDelayedMarking << ArenaShift)->aheader;
}
inline void
ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader)
{
JS_ASSERT(!(uintptr_t(aheader) & ArenaMask));
hasDelayedMarking = 1;
nextDelayedMarking = aheader->arenaAddress() >> ArenaShift;
}
JS_ALWAYS_INLINE void
ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color,
uintptr_t **wordp, uintptr_t *maskp)
{
size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color;
JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk);
*maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD);
*wordp = &bitmap[bit / JS_BITS_PER_WORD];
}
static void
AssertValidColor(const void *thing, uint32_t color)
{
#ifdef DEBUG
ArenaHeader *aheader = reinterpret_cast<const Cell *>(thing)->arenaHeader();
JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize);
#endif
}
inline ArenaHeader *
Cell::arenaHeader() const
{
uintptr_t addr = address();
addr &= ~ArenaMask;
return reinterpret_cast<ArenaHeader *>(addr);
}
Chunk *
Cell::chunk() const
{
uintptr_t addr = uintptr_t(this);
JS_ASSERT(addr % Cell::CellSize == 0);
addr &= ~(ChunkSize - 1);
return reinterpret_cast<Chunk *>(addr);
}
AllocKind
Cell::getAllocKind() const
{
return arenaHeader()->getAllocKind();
}
bool
Cell::isMarked(uint32_t color /* = BLACK */) const
{
AssertValidColor(this, color);
return chunk()->bitmap.isMarked(this, color);
}
bool
Cell::markIfUnmarked(uint32_t color /* = BLACK */) const
{
AssertValidColor(this, color);
return chunk()->bitmap.markIfUnmarked(this, color);
}
void
Cell::unmark(uint32_t color) const
{
JS_ASSERT(color != BLACK);
AssertValidColor(this, color);
chunk()->bitmap.unmark(this, color);
}
JSCompartment *
Cell::compartment() const
{
return arenaHeader()->compartment;
}
#ifdef DEBUG
bool
Cell::isAligned() const
{
return Arena::isAligned(address(), arenaHeader()->getThingSize());
}
#endif
} /* namespace gc */
} /* namespace js */
#endif /* gc_heap_h___ */

View File

@ -1,51 +1,22 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey global object code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_root_h__
#define jsgc_root_h__
#include "jspubtd.h"
#include "js/Utility.h"
#ifdef __cplusplus
#include "mozilla/TypeTraits.h"
#include "jsapi.h"
#include "js/TemplateLib.h"
#include "js/Utility.h"
namespace JS {
/*
@ -76,75 +47,159 @@ namespace JS {
* on the type T of the value being rooted, for which RootMethods<T> must
* have an instantiation.
*
* - Root<T> roots an existing stack allocated variable or other location of
* type T. This is typically used either when a variable only needs to be
* rooted on certain rare paths, or when a function takes a bare GC thing
* pointer as an argument and needs to root it. In the latter case a
* Handle<T> is generally preferred, see below.
* - Rooted<T> declares a variable of type T, whose value is always rooted.
* Rooted<T> may be automatically coerced to a Handle<T>, below. Rooted<T>
* should be used whenever a local variable's value may be held live across a
* call which can allocate GC things or otherwise trigger a GC.
*
* - RootedVar<T> declares a variable of type T, whose value is always rooted.
*
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
* take GC things or values as arguments and need to root those arguments
* should generally replace those arguments with handles and avoid any
* explicit rooting. This has two benefits. First, when several such
* functions call each other then redundant rooting of multiple copies of the
* GC thing can be avoided. Second, if the caller does not pass a rooted
* value a compile error will be generated, which is quicker and easier to
* fix than when relying on a separate rooting analysis.
* - Handle<T> is a const reference to a Rooted<T>. Functions which take GC
* things or values as arguments and need to root those arguments should
* generally use handles for those arguments and avoid any explicit rooting.
* This has two benefits. First, when several such functions call each other
* then redundant rooting of multiple copies of the GC thing can be avoided.
* Second, if the caller does not pass a rooted value a compile error will be
* generated, which is quicker and easier to fix than when relying on a
* separate rooting analysis.
*/
template <typename T> class Root;
template <typename T> class RootedVar;
template <typename T> class Rooted;
template <typename T>
struct RootMethods { };
/*
* Reference to a stack location rooted for GC. See the "Moving GC Stack
* Rooting" comment above.
* Handle provides an implicit constructor for NullPtr so that, given:
* foo(Handle<JSObject*> h);
* callers can simply write:
* foo(NullPtr());
* which avoids creating a Rooted<JSObject*> just to pass NULL.
*/
struct NullPtr
{
static void * const constNullValue;
};
template <typename T>
class HandleBase {};
/*
* Reference to a T that has been rooted elsewhere. This is most useful
* as a parameter type, which guarantees that the T lvalue is properly
* rooted. See "Move GC Stack Rooting" above.
*
* If you want to add additional methods to Handle for a specific
* specialization, define a HandleBase<T> specialization containing them.
*/
template <typename T>
class Handle
class Handle : public HandleBase<T>
{
public:
/* Copy handles of different types, with implicit coercion. */
template <typename S> Handle(Handle<S> handle) {
testAssign<S>();
/* Creates a handle from a handle of a type convertible to T. */
template <typename S>
Handle(Handle<S> handle,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
{
ptr = reinterpret_cast<const T *>(handle.address());
}
/* Get a handle from a rooted stack location, with implicit coercion. */
template <typename S> inline Handle(const Root<S> &root);
template <typename S> inline Handle(const RootedVar<S> &root);
/* Create a handle for a NULL pointer. */
Handle(NullPtr) {
typedef typename js::tl::StaticAssert<js::tl::IsPointerType<T>::result>::result _;
ptr = reinterpret_cast<const T *>(&NullPtr::constNullValue);
}
const T *address() { return ptr; }
/*
* This may be called only if the location of the T is guaranteed
* to be marked (for some reason other than being a Rooted),
* e.g., if it is guaranteed to be reachable from an implicit root.
*
* Create a Handle from a raw location of a T.
*/
static Handle fromMarkedLocation(const T *p) {
Handle h;
h.ptr = p;
return h;
}
operator T () { return value(); }
T operator ->() { return value(); }
/*
* Construct a handle from an explicitly rooted location. This is the
* normal way to create a handle, and normally happens implicitly.
*/
template <typename S>
inline
Handle(Rooted<S> &root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
const T *address() const { return ptr; }
T get() const { return *ptr; }
operator T () const { return get(); }
T operator ->() const { return get(); }
private:
Handle() {}
const T *ptr;
T value() { return *ptr; }
template <typename S>
void testAssign() {
#ifdef DEBUG
T a = RootMethods<T>::initial();
S b = RootMethods<S>::initial();
a = b;
(void)a;
#endif
}
void operator =(S v) MOZ_DELETE;
};
typedef Handle<JSObject*> HandleObject;
typedef Handle<JSFunction*> HandleFunction;
typedef Handle<JSScript*> HandleScript;
typedef Handle<JSString*> HandleString;
typedef Handle<jsid> HandleId;
typedef Handle<Value> HandleValue;
template <typename T>
class MutableHandleBase {};
/*
* Similar to a handle, but the underlying storage can be changed. This is
* useful for outparams.
*
* If you want to add additional methods to MutableHandle for a specific
* specialization, define a MutableHandleBase<T> specialization containing
* them.
*/
template <typename T>
class MutableHandle : public MutableHandleBase<T>
{
public:
template <typename S>
MutableHandle(MutableHandle<S> handle,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
{
this->ptr = reinterpret_cast<const T *>(handle.address());
}
template <typename S>
inline
MutableHandle(Rooted<S> *root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
void set(T v)
{
JS_ASSERT(!RootMethods<T>::poisoned(v));
*ptr = v;
}
T *address() const { return ptr; }
T get() const { return *ptr; }
operator T () const { return get(); }
T operator ->() const { return get(); }
private:
MutableHandle() {}
T *ptr;
};
typedef MutableHandle<JSObject*> MutableHandleObject;
typedef MutableHandle<Value> MutableHandleValue;
template <typename T>
struct RootMethods<T *>
{
@ -153,76 +208,103 @@ struct RootMethods<T *>
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
};
template <typename T>
class RootedBase {};
/*
* Root a stack location holding a GC thing. This takes a stack pointer
* and ensures that throughout its lifetime the referenced variable
* will remain pinned against a moving GC.
* Local variable of type T whose value is always rooted. This is typically
* used for local variables, or for non-rooted values being passed to a
* function that requires a handle, e.g. Foo(Root<T>(cx, x)).
*
* It is important to ensure that the location referenced by a Root is
* initialized, as otherwise the GC may try to use the the uninitialized value.
* It is generally preferable to use either RootedVar for local variables, or
* Handle for arguments.
* If you want to add additional methods to Rooted for a specific
* specialization, define a RootedBase<T> specialization containing them.
*/
template <typename T>
class Root
class Rooted : public RootedBase<T>
{
public:
Root(JSContext *cx_, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
void init(JSContext *cx_)
{
#ifdef JSGC_ROOT_ANALYSIS
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
ContextFriendFields *cx = ContextFriendFields::get(cx_);
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
this->stack = reinterpret_cast<Rooted<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
JS_ASSERT(!RootMethods<T>::poisoned(ptr));
#endif
JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
this->ptr = ptr;
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~Root()
public:
Rooted(JSContext *cx) : ptr(RootMethods<T>::initial()) { init(cx); }
Rooted(JSContext *cx, T initial) : ptr(initial) { init(cx); }
~Rooted()
{
#ifdef JSGC_ROOT_ANALYSIS
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
JS_ASSERT(*stack == this);
*stack = prev;
#endif
}
#ifdef JSGC_ROOT_ANALYSIS
Root<T> *previous() { return prev; }
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
Rooted<T> *previous() { return prev; }
#endif
const T *address() const { return ptr; }
operator T () const { return ptr; }
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & get() { return ptr; }
const T & get() const { return ptr; }
T & operator =(T value)
{
JS_ASSERT(!RootMethods<T>::poisoned(value));
ptr = value;
return ptr;
}
T & operator =(const Rooted &value)
{
ptr = value;
return ptr;
}
private:
#ifdef JSGC_ROOT_ANALYSIS
Root<T> **stack, *prev;
#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
Rooted<T> **stack, *prev;
#endif
const T *ptr;
T ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
Rooted() MOZ_DELETE;
Rooted(const Rooted &) MOZ_DELETE;
};
template<typename T> template <typename S>
inline
Handle<T>::Handle(const Root<S> &root)
Handle<T>::Handle(Rooted<S> &root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
{
testAssign<S>();
ptr = reinterpret_cast<const T *>(root.address());
}
typedef Root<JSObject*> RootObject;
typedef Root<JSFunction*> RootFunction;
typedef Root<JSString*> RootString;
typedef Root<jsid> RootId;
typedef Root<Value> RootValue;
template<typename T> template <typename S>
inline
MutableHandle<T>::MutableHandle(Rooted<S> *root,
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
{
ptr = root->address();
}
typedef Rooted<JSObject*> RootedObject;
typedef Rooted<JSFunction*> RootedFunction;
typedef Rooted<JSScript*> RootedScript;
typedef Rooted<JSString*> RootedString;
typedef Rooted<jsid> RootedId;
typedef Rooted<Value> RootedValue;
/*
* Mark a stack location as a root for the rooting analysis, without actually
@ -238,18 +320,30 @@ class SkipRoot
const uint8_t *start;
const uint8_t *end;
public:
template <typename T>
SkipRoot(JSContext *cx_, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
void init(ContextFriendFields *cx, const T *ptr, size_t count)
{
ContextFriendFields *cx = ContextFriendFields::get(cx_);
this->stack = &cx->skipGCRooters;
this->prev = *stack;
*stack = this;
this->start = (const uint8_t *) ptr;
this->end = this->start + sizeof(T);
this->end = this->start + (sizeof(T) * count);
}
public:
template <typename T>
SkipRoot(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(ContextFriendFields::get(cx), ptr, 1);
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
template <typename T>
SkipRoot(JSContext *cx, const T *ptr, size_t count
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
init(ContextFriendFields::get(cx), ptr, count);
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
@ -275,74 +369,66 @@ class SkipRoot
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
template <typename T>
SkipRoot(JSContext *cx, const T *ptr, size_t count
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/* Make a local variable which stays rooted throughout its lifetime. */
template <typename T>
class RootedVar
{
public:
RootedVar(JSContext *cx)
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
{}
#ifdef DEBUG
JS_FRIEND_API(bool) IsRootingUnnecessaryForContext(JSContext *cx);
JS_FRIEND_API(void) SetRootingUnnecessaryForContext(JSContext *cx, bool value);
JS_FRIEND_API(bool) RelaxRootChecksForContext(JSContext *cx);
#endif
RootedVar(JSContext *cx, T initial)
: ptr(initial), root(cx, &ptr)
{}
operator T () const { return ptr; }
T operator ->() const { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T & reference() { return ptr; }
T raw() { return ptr; }
/*
* This method is only necessary due to an obscure C++98 requirement (that
* there be an accessible, usable copy constructor when passing a temporary
* to an implicitly-called constructor for use with a const-ref parameter).
* (Head spinning yet?) We can remove this when we build the JS engine
* with -std=c++11.
*/
operator Handle<T> () const { return Handle<T>(*this); }
T & operator =(T value)
class AssertRootingUnnecessary {
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
JSContext *cx;
bool prev;
public:
AssertRootingUnnecessary(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
: cx(cx)
{
JS_ASSERT(!RootMethods<T>::poisoned(value));
ptr = value;
return ptr;
JS_GUARD_OBJECT_NOTIFIER_INIT;
#ifdef DEBUG
prev = IsRootingUnnecessaryForContext(cx);
SetRootingUnnecessaryForContext(cx, true);
#endif
}
T & operator =(const RootedVar &value)
{
ptr = value;
return ptr;
~AssertRootingUnnecessary() {
#ifdef DEBUG
SetRootingUnnecessaryForContext(cx, prev);
#endif
}
private:
T ptr;
Root<T> root;
RootedVar() MOZ_DELETE;
RootedVar(const RootedVar &) MOZ_DELETE;
};
template <typename T> template <typename S>
inline
Handle<T>::Handle(const RootedVar<S> &root)
{
testAssign<S>();
ptr = reinterpret_cast<const T *>(root.address());
}
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
extern void
CheckStackRoots(JSContext *cx);
#endif
typedef RootedVar<JSObject*> RootedVarObject;
typedef RootedVar<JSFunction*> RootedVarFunction;
typedef RootedVar<JSString*> RootedVarString;
typedef RootedVar<jsid> RootedVarId;
typedef RootedVar<Value> RootedVarValue;
/*
* Hook for dynamic root analysis. Checks the native stack and poisons
* references to GC things which have not been rooted.
*/
inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true)
{
#ifdef DEBUG
JS_ASSERT(!IsRootingUnnecessaryForContext(cx));
# if defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
if (relax && RelaxRootChecksForContext(cx))
return;
CheckStackRoots(cx);
# endif
#endif
}
} /* namespace JS */

View File

@ -1,41 +1,9 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey JavaScript engine.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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___
@ -56,19 +24,26 @@ enum Phase {
PHASE_WAIT_BACKGROUND_THREAD,
PHASE_PURGE,
PHASE_MARK,
PHASE_MARK_DISCARD_CODE,
PHASE_MARK_ROOTS,
PHASE_MARK_TYPES,
PHASE_MARK_DELAYED,
PHASE_MARK_OTHER,
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_DISCARD_CODE,
PHASE_SWEEP_DISCARD_CODE,
PHASE_DISCARD_ANALYSIS,
PHASE_DISCARD_TI,
PHASE_FREE_TI_ARENA,
PHASE_SWEEP_TYPES,
PHASE_CLEAR_SCRIPT_ANALYSIS,
PHASE_FINALIZE_END,
@ -116,13 +91,19 @@ struct Statistics {
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)
: reason(reason), resetReason(NULL), start(start)
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
{
PodArrayZero(phaseTimes);
}
@ -130,6 +111,7 @@ struct Statistics {
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; }
@ -138,7 +120,7 @@ struct Statistics {
Vector<SliceData, 8, SystemAllocPolicy> slices;
/* Most recent time when the given phase started. */
int64_t phaseStarts[PHASE_LIMIT];
int64_t phaseStartTimes[PHASE_LIMIT];
/* Total time in a given phase for this GC. */
int64_t phaseTimes[PHASE_LIMIT];

View File

@ -2,42 +2,9 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_config_h___
#define js_config_h___
@ -96,4 +63,7 @@
correct. */
/* #undef JS_METHODJIT */
/* Define to 1 to enable support for E4X (ECMA-357), 0 to disable it. */
#define JS_HAS_XML_SUPPORT 1
#endif /* js_config_h___ */

View File

@ -1,41 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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/. */
/*
* This is the JavaScript error message file.
@ -147,8 +114,8 @@ MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode")
MSG_DEF(JSMSG_UNUSED64, 64, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range")
MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)")
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_UNUSED67, 67, 0, JSEXN_NONE, "")
MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
@ -258,7 +225,7 @@ MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML char
MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace")
MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name")
MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression")
MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}")
MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 0, JSEXN_TYPEERR, "already executing generator")
MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression")
MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}")
MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}")
@ -378,4 +345,10 @@ MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterabl
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property")
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties")
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter")
MSG_DEF(JSMSG_NO_REST_NAME, 296, 0, JSEXN_SYNTAXERR, "no parameter name after ...")
MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter")
MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default")
MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression")

View File

@ -1,44 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* November 13, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
* Brendan Eich <brendan@mozilla.org> (Original Author)
* Chris Waterson <waterson@netscape.com>
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
* Luke Wagner <lw@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jshashtable_h_
#define jshashtable_h_
@ -97,7 +62,7 @@ class HashTableEntry {
JS_ASSERT(isLive()); keyHash |= collisionBit;
}
void unsetCollision() { keyHash &= ~sCollisionBit; }
bool hasCollision() const { JS_ASSERT(isLive()); return keyHash & sCollisionBit; }
bool hasCollision() const { return keyHash & sCollisionBit; }
bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; }
HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; }
};
@ -177,21 +142,23 @@ class HashTable : private AllocPolicy
protected:
friend class HashTable;
Range(Entry *c, Entry *e) : cur(c), end(e) {
Range(Entry *c, Entry *e) : cur(c), end(e), validEntry(true) {
while (cur < end && !cur->isLive())
++cur;
}
Entry *cur, *end;
DebugOnly<bool> validEntry;
public:
Range() : cur(NULL), end(NULL) {}
Range() : cur(NULL), end(NULL), validEntry(false) {}
bool empty() const {
return cur == end;
}
T &front() const {
JS_ASSERT(validEntry);
JS_ASSERT(!empty());
return cur->t;
}
@ -200,6 +167,7 @@ class HashTable : private AllocPolicy
JS_ASSERT(!empty());
while (++cur < end && !cur->isLive())
continue;
validEntry = true;
}
};
@ -217,7 +185,7 @@ class HashTable : private AllocPolicy
friend class HashTable;
HashTable &table;
bool added;
bool rekeyed;
bool removed;
/* Not copyable. */
@ -226,7 +194,7 @@ class HashTable : private AllocPolicy
public:
template<class Map> explicit
Enum(Map &map) : Range(map.all()), table(map.impl), added(false), removed(false) {}
Enum(Map &map) : Range(map.all()), table(map.impl), rekeyed(false), removed(false) {}
/*
* Removes the |front()| element from the table, leaving |front()|
@ -240,6 +208,7 @@ class HashTable : private AllocPolicy
void removeFront() {
table.remove(*this->cur);
removed = true;
this->validEntry = false;
}
/*
@ -247,35 +216,29 @@ class HashTable : private AllocPolicy
* a new key at the new Lookup position. |front()| is invalid after
* this operation until the next call to |popFront()|.
*/
void rekeyFront(Key &k) {
void rekeyFront(const Lookup &l, const Key &k) {
JS_ASSERT(&k != &HashPolicy::getKey(this->cur->t));
JS_ASSERT(!table.match(*this->cur, k));
Entry e = *this->cur;
HashPolicy::setKey(e.t, k);
if (match(*this->cur, l))
return;
typename HashTableEntry<T>::NonConstT t = this->cur->t;
HashPolicy::setKey(t, const_cast<Key &>(k));
table.remove(*this->cur);
table.add(k, e);
added = true;
table.putNewInfallible(l, t);
rekeyed = true;
this->validEntry = false;
}
void rekeyFront(const Key &k) {
rekeyFront(k, k);
}
/* Potentially rehashes the table. */
~Enum() {
if (added)
table.checkOverloaded();
if (rekeyed)
table.checkOverRemoved();
if (removed)
table.checkUnderloaded();
}
/* Can be used to end the enumeration before the destructor. */
void endEnumeration() {
if (added) {
table.checkOverloaded();
added = false;
}
if (removed) {
table.checkUnderloaded();
removed = false;
}
}
};
private:
@ -301,6 +264,7 @@ class HashTable : private AllocPolicy
uint32_t grows; /* table expansions */
uint32_t shrinks; /* table contractions */
uint32_t compresses; /* table compressions */
uint32_t rehashes; /* tombstone decontaminations */
} stats;
# define METER(x) x
#else
@ -384,7 +348,7 @@ class HashTable : private AllocPolicy
mutationCount(0)
{}
bool init(uint32_t length)
MOZ_WARN_UNUSED_RESULT bool init(uint32_t length)
{
/* Make sure that init isn't called twice. */
JS_ASSERT(table == NULL);
@ -533,8 +497,9 @@ class HashTable : private AllocPolicy
*/
Entry &findFreeEntry(HashNumber keyHash)
{
METER(stats.searches++);
JS_ASSERT(!(keyHash & sCollisionBit));
JS_ASSERT(table);
METER(stats.searches++);
/* N.B. the |keyHash| has already been distributed. */
@ -543,7 +508,7 @@ class HashTable : private AllocPolicy
Entry *entry = &table[h1];
/* Miss: return space for a new entry. */
if (entry->isFree()) {
if (!entry->isLive()) {
METER(stats.misses++);
return *entry;
}
@ -559,14 +524,16 @@ class HashTable : private AllocPolicy
h1 = applyDoubleHash(h1, dh);
entry = &table[h1];
if (entry->isFree()) {
if (!entry->isLive()) {
METER(stats.misses++);
return *entry;
}
}
}
bool changeTableSize(int deltaLog2)
enum RebuildStatus { NotOverloaded, Rehashed, RehashFailed };
RebuildStatus changeTableSize(int deltaLog2)
{
/* Look, but don't touch, until we succeed in getting new entry store. */
Entry *oldTable = table;
@ -575,12 +542,12 @@ class HashTable : private AllocPolicy
uint32_t newCapacity = JS_BIT(newLog2);
if (newCapacity > sMaxCapacity) {
this->reportAllocOverflow();
return false;
return RehashFailed;
}
Entry *newTable = createTable(*this, newCapacity);
if (!newTable)
return false;
return RehashFailed;
/* We can't fail from here on, so update table parameters. */
setTableSizeLog2(newLog2);
@ -597,30 +564,13 @@ class HashTable : private AllocPolicy
}
destroyTable(*this, oldTable, oldCap);
return true;
return Rehashed;
}
void add(const Lookup &l, const Entry &e)
{
HashNumber keyHash = prepareHash(l);
Entry &entry = lookup(l, keyHash, sCollisionBit);
if (entry.isRemoved()) {
METER(stats.addOverRemoved++);
removedCount--;
keyHash |= sCollisionBit;
}
entry.t = e.t;
entry.setLive(keyHash);
entryCount++;
mutationCount++;
}
bool checkOverloaded()
RebuildStatus checkOverloaded()
{
if (!overloaded())
return false;
return NotOverloaded;
/* Compress if a quarter or more of all entries are removed. */
int deltaLog2;
@ -635,9 +585,21 @@ class HashTable : private AllocPolicy
return changeTableSize(deltaLog2);
}
/* Infallibly rehash the table if we are overloaded with removals. */
void checkOverRemoved()
{
if (overloaded()) {
METER(stats.rehashes++);
rehashTable();
JS_ASSERT(!overloaded());
}
}
void remove(Entry &e)
{
JS_ASSERT(table);
METER(stats.removes++);
if (e.hasCollision()) {
e.setRemoved();
removedCount++;
@ -657,6 +619,52 @@ class HashTable : private AllocPolicy
}
}
/*
* This is identical to changeTableSize(currentSize), but without requiring
* a second table. We do this by recycling the collision bits to tell us if
* the element is already inserted or still waiting to be inserted. Since
* already-inserted elements win any conflicts, we get the same table as we
* would have gotten through random insertion order.
*/
void rehashTable()
{
removedCount = 0;
for (size_t i = 0; i < capacity(); ++i)
table[i].unsetCollision();
for (size_t i = 0; i < capacity();) {
Entry *src = &table[i];
if (!src->isLive() || src->hasCollision()) {
++i;
continue;
}
HashNumber keyHash = src->getKeyHash();
HashNumber h1 = hash1(keyHash, hashShift);
DoubleHash dh = hash2(keyHash, hashShift);
Entry *tgt = &table[h1];
while (true) {
if (!tgt->hasCollision()) {
Swap(*src, *tgt);
tgt->setCollision();
break;
}
h1 = applyDoubleHash(h1, dh);
tgt = &table[h1];
}
}
/*
* TODO: this algorithm leaves collision bits on *all* elements, even if
* they are on no collision path. We have the option of setting the
* collision bits correctly on a subsequent pass or skipping the rehash
* unless we are totally filled with tombstones: benchmark to find out
* which approach is best.
*/
}
public:
void clear()
{
@ -688,22 +696,27 @@ class HashTable : private AllocPolicy
}
Range all() const {
JS_ASSERT(table);
return Range(table, table + capacity());
}
bool empty() const {
JS_ASSERT(table);
return !entryCount;
}
uint32_t count() const {
JS_ASSERT(table);
return entryCount;
}
uint32_t capacity() const {
JS_ASSERT(table);
return JS_BIT(sHashBits - hashShift);
}
uint32_t generation() const {
JS_ASSERT(table);
return gen;
}
@ -747,8 +760,11 @@ class HashTable : private AllocPolicy
removedCount--;
p.keyHash |= sCollisionBit;
} else {
if (checkOverloaded())
/* Preserve the validity of |p.entry|. */
/* Preserve the validity of |p.entry|. */
RebuildStatus status = checkOverloaded();
if (status == RehashFailed)
return false;
if (status == Rehashed)
p.entry = &findFreeEntry(p.keyHash);
}
@ -779,6 +795,34 @@ class HashTable : private AllocPolicy
return true;
}
void putNewInfallible(const Lookup &l, const T &t)
{
JS_ASSERT(table);
HashNumber keyHash = prepareHash(l);
Entry *entry = &findFreeEntry(keyHash);
if (entry->isRemoved()) {
METER(stats.addOverRemoved++);
removedCount--;
keyHash |= sCollisionBit;
}
entry->t = t;
entry->setLive(keyHash);
entryCount++;
mutationCount++;
}
bool putNew(const Lookup &l, const T &t)
{
if (checkOverloaded() == RehashFailed)
return false;
putNewInfallible(l, t);
return true;
}
bool relookupOrAdd(AddPtr& p, const Lookup &l, const T& t)
{
p.mutationCount = mutationCount;
@ -791,6 +835,7 @@ class HashTable : private AllocPolicy
void remove(Ptr p)
{
JS_ASSERT(table);
ReentrancyGuard g(*this);
JS_ASSERT(p.found());
remove(*p.entry);
@ -1163,9 +1208,7 @@ class HashMap
/* Like put, but assert that the given key is not already present. */
bool putNew(const Key &k, const Value &v) {
AddPtr p = lookupForAdd(k);
JS_ASSERT(!p);
return add(p, k, v);
return impl.putNew(k, Entry(k, v));
}
/* Add (k,defaultValue) if k no found. Return false-y Ptr on oom. */
@ -1371,15 +1414,11 @@ class HashSet
/* Like put, but assert that the given key is not already present. */
bool putNew(const T &t) {
AddPtr p = lookupForAdd(t);
JS_ASSERT(!p);
return add(p, t);
return impl.putNew(t, t);
}
bool putNew(const Lookup &l, const T &t) {
AddPtr p = lookupForAdd(l);
JS_ASSERT(!p);
return add(p, t);
return impl.putNew(l, t);
}
void remove(const Lookup &l) {

View File

@ -1,40 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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/. */
/*
* This section typedefs the old 'native' types to the new <stdint.h> types.

View File

@ -1,41 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is about:memory glue.
*
* The Initial Developer of the Original Code is
* Ms2ger <ms2ger@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_MemoryMetrics_h
#define js_MemoryMetrics_h
@ -62,6 +30,53 @@ struct TypeInferenceSizes
size_t objects;
size_t tables;
size_t temporary;
void add(TypeInferenceSizes &sizes) {
this->scripts += sizes.scripts;
this->objects += sizes.objects;
this->tables += sizes.tables;
this->temporary += sizes.temporary;
}
};
// These measurements relate directly to the JSRuntime, and not to
// compartments within it.
struct RuntimeSizes
{
RuntimeSizes()
: object(0)
, atomsTable(0)
, contexts(0)
, dtoa(0)
, temporary(0)
, mjitCode(0)
, regexpCode(0)
, unusedCodeMemory(0)
, stackCommitted(0)
, gcMarker(0)
, mathCache(0)
, scriptFilenames(0)
, compartmentObjects(0)
{}
size_t object;
size_t atomsTable;
size_t contexts;
size_t dtoa;
size_t temporary;
size_t mjitCode;
size_t regexpCode;
size_t unusedCodeMemory;
size_t stackCommitted;
size_t gcMarker;
size_t mathCache;
size_t scriptFilenames;
// This is the exception to the "RuntimeSizes doesn't measure things within
// compartments" rule. We combine the sizes of all the JSCompartment
// objects into a single measurement because each one is fairly small, and
// they're all the same size.
size_t compartmentObjects;
};
struct CompartmentStats
@ -70,10 +85,14 @@ struct CompartmentStats
memset(this, 0, sizeof(*this));
}
void *extra;
size_t gcHeapArenaHeaders;
size_t gcHeapArenaPadding;
size_t gcHeapArenaUnused;
// These fields can be used by embedders.
void *extra1;
void *extra2;
// If you add a new number, remember to update add() and maybe
// gcHeapThingsSize()!
size_t gcHeapArenaAdmin;
size_t gcHeapUnusedGcThings;
size_t gcHeapObjectsNonFunction;
size_t gcHeapObjectsFunction;
@ -83,84 +102,117 @@ struct CompartmentStats
size_t gcHeapShapesBase;
size_t gcHeapScripts;
size_t gcHeapTypeObjects;
#if JS_HAS_XML_SUPPORT
size_t gcHeapXML;
#endif
size_t objectSlots;
size_t objectElements;
size_t objectMisc;
size_t objectPrivate;
size_t stringChars;
size_t shapesExtraTreeTables;
size_t shapesExtraDictTables;
size_t shapesExtraTreeShapeKids;
size_t shapesCompartmentTables;
size_t scriptData;
#ifdef JS_METHODJIT
size_t mjitCode;
size_t mjitData;
#endif
size_t crossCompartmentWrappers;
TypeInferenceSizes typeInferenceSizes;
// Add cStats's numbers to this object's numbers.
void add(CompartmentStats &cStats) {
#define ADD(x) this->x += cStats.x
ADD(gcHeapArenaAdmin);
ADD(gcHeapUnusedGcThings);
ADD(gcHeapObjectsNonFunction);
ADD(gcHeapObjectsFunction);
ADD(gcHeapStrings);
ADD(gcHeapShapesTree);
ADD(gcHeapShapesDict);
ADD(gcHeapShapesBase);
ADD(gcHeapScripts);
ADD(gcHeapTypeObjects);
#if JS_HAS_XML_SUPPORT
ADD(gcHeapXML);
#endif
ADD(objectSlots);
ADD(objectElements);
ADD(objectMisc);
ADD(objectPrivate);
ADD(stringChars);
ADD(shapesExtraTreeTables);
ADD(shapesExtraDictTables);
ADD(shapesExtraTreeShapeKids);
ADD(shapesCompartmentTables);
ADD(scriptData);
ADD(mjitData);
ADD(crossCompartmentWrappers);
#undef ADD
typeInferenceSizes.add(cStats.typeInferenceSizes);
}
// The size of all the live things in the GC heap.
size_t gcHeapThingsSize();
};
struct RuntimeStats
{
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
: runtimeObject(0)
, runtimeAtomsTable(0)
, runtimeContexts(0)
, runtimeNormal(0)
, runtimeTemporary(0)
, runtimeRegexpCode(0)
, runtimeStackCommitted(0)
, runtimeGCMarker(0)
: runtime()
, gcHeapChunkTotal(0)
, gcHeapChunkCleanUnused(0)
, gcHeapChunkDirtyUnused(0)
, gcHeapChunkCleanDecommitted(0)
, gcHeapChunkDirtyDecommitted(0)
, gcHeapArenaUnused(0)
, gcHeapDecommittedArenas(0)
, gcHeapUnusedChunks(0)
, gcHeapUnusedArenas(0)
, gcHeapUnusedGcThings(0)
, gcHeapChunkAdmin(0)
, gcHeapUnusedPercentage(0)
, totalObjects(0)
, totalShapes(0)
, totalScripts(0)
, totalStrings(0)
#ifdef JS_METHODJIT
, totalMjit(0)
#endif
, totalTypeInference(0)
, totalAnalysisTemp(0)
, gcHeapGcThings(0)
, totals()
, compartmentStatsVector()
, currCompartmentStats(NULL)
, mallocSizeOf(mallocSizeOf)
{}
size_t runtimeObject;
size_t runtimeAtomsTable;
size_t runtimeContexts;
size_t runtimeNormal;
size_t runtimeTemporary;
size_t runtimeRegexpCode;
size_t runtimeStackCommitted;
size_t runtimeGCMarker;
size_t gcHeapChunkTotal;
size_t gcHeapChunkCleanUnused;
size_t gcHeapChunkDirtyUnused;
size_t gcHeapChunkCleanDecommitted;
size_t gcHeapChunkDirtyDecommitted;
size_t gcHeapArenaUnused;
size_t gcHeapChunkAdmin;
size_t gcHeapUnusedPercentage;
size_t totalObjects;
size_t totalShapes;
size_t totalScripts;
size_t totalStrings;
#ifdef JS_METHODJIT
size_t totalMjit;
#endif
size_t totalTypeInference;
size_t totalAnalysisTemp;
RuntimeSizes runtime;
// If you add a new number, remember to update the constructor!
// Here's a useful breakdown of the GC heap.
//
// - rtStats.gcHeapChunkTotal
// - decommitted bytes
// - rtStats.gcHeapDecommittedArenas (decommitted arenas in non-empty chunks)
// - unused bytes
// - rtStats.gcHeapUnusedChunks (empty chunks)
// - rtStats.gcHeapUnusedArenas (empty arenas within non-empty chunks)
// - rtStats.total.gcHeapUnusedGcThings (empty GC thing slots within non-empty arenas)
// - used bytes
// - rtStats.gcHeapChunkAdmin
// - rtStats.total.gcHeapArenaAdmin
// - rtStats.gcHeapGcThings (in-use GC things)
//
// It's possible that some arenas in empty chunks may be decommitted, but
// we don't count those under rtStats.gcHeapDecommittedArenas because (a)
// it's rare, and (b) this means that rtStats.gcHeapUnusedChunks is a
// multiple of the chunk size, which is good.
size_t gcHeapChunkTotal;
size_t gcHeapDecommittedArenas;
size_t gcHeapUnusedChunks;
size_t gcHeapUnusedArenas;
size_t gcHeapUnusedGcThings;
size_t gcHeapChunkAdmin;
size_t gcHeapGcThings;
// The sum of all compartment's measurements.
CompartmentStats totals;
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
CompartmentStats *currCompartmentStats;
@ -171,8 +223,16 @@ struct RuntimeStats
#ifdef JS_THREADSAFE
class ObjectPrivateVisitor
{
public:
// Within CollectRuntimeStats, this method is called for each JS object
// that has a private slot containing an nsISupports pointer.
virtual size_t sizeOfIncludingThis(void *aSupports) = 0;
};
extern JS_PUBLIC_API(bool)
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv);
extern JS_PUBLIC_API(int64_t)
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf);

View File

@ -1,42 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Luke Wagner <luke@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_template_lib_h__
#define js_template_lib_h__
@ -174,10 +141,13 @@ template <typename T> struct IsPodType<T *> { static const bool result =
template <bool cond, typename T, T v1, T v2> struct If { static const T result = v1; };
template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
template <class T> struct IsPointerType { static const bool result = false; };
template <class T> struct IsPointerType<T *> { static const bool result = true; };
/*
* Traits class for identifying types that are implicitly barriered.
*/
template <class T> struct IsPostBarrieredType { static const bool result = false; };
template <class T> struct IsRelocatableHeapType { static const bool result = true; };
} /* namespace tl */
} /* namespace js */

View File

@ -1,46 +1,15 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_utility_h__
#define js_utility_h__
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include <stdlib.h>
#include <string.h>
@ -53,6 +22,7 @@
#include "jstypes.h"
#ifdef __cplusplus
# include "mozilla/Scoped.h"
/* The public JS engine namespace. */
namespace JS {}
@ -97,6 +67,9 @@ JS_BEGIN_EXTERN_C
#define JS_STATIC_ASSERT(cond) MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
extern MOZ_NORETURN JS_PUBLIC_API(void)
JS_Assert(const char *s, const char *file, int ln);
/*
* Abort the process in a non-graceful manner. This will cause a core file,
* call to the debugger or other moral equivalent as well as causing the
@ -626,6 +599,15 @@ public:
class UnwantedForeground : public Foreground {
};
template <typename T>
struct ScopedDeletePtrTraits
{
typedef T *type;
static T *empty() { return NULL; }
static void release(T *ptr) { Foreground::delete_(ptr); }
};
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
} /* namespace js */
/*
@ -847,7 +829,7 @@ class MoveRef {
explicit MoveRef(T &t) : pointer(&t) { }
T &operator*() const { return *pointer; }
T *operator->() const { return pointer; }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__clang__)
/*
* If MoveRef is used in a rvalue position (which is expected), we can
* end up in a situation where, without this ifdef, we would try to pass

View File

@ -1,42 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* June 12, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
* Luke Wagner <lw@mozilla.com>
* Nicholas Nethercote <nnethercote@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsvector_h_
#define jsvector_h_
@ -213,7 +180,7 @@ struct VectorImpl<T, N, AP, true>
template <class T, size_t N, class AllocPolicy>
class Vector : private AllocPolicy
{
typedef typename tl::StaticAssert<!tl::IsPostBarrieredType<T>::result>::result _;
typedef typename tl::StaticAssert<tl::IsRelocatableHeapType<T>::result>::result _;
/* utilities */
@ -596,7 +563,12 @@ Vector<T,N,AP>::~Vector()
*/
template <class T, size_t N, class AP>
STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc)
#ifdef DEBUG
/* gcc (ARM, x86) compiler bug workaround - See bug 694694 */
JS_NEVER_INLINE bool
#else
inline bool
#endif
Vector<T,N,AP>::calculateNewCapacity(size_t curLength, size_t lengthInc,
size_t &newCap)
{

View File

@ -1,40 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* July 16, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsalloc_h_
#define jsalloc_h_

View File

@ -1 +1 @@
e71bf3943ff22eeb475acd419c7005556859f6c4
37b6af08d1e6059f152ae515d8d7422a346cf7ed

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsatom_h___
#define jsatom_h___
@ -67,14 +34,37 @@ JSID_FROM_BITS(size_t bits)
return id;
}
/*
* Must not be used on atoms that are representable as integer jsids.
* Prefer NameToId or AtomToId over this function:
*
* A PropertyName is an atom that does not contain an integer in the range
* [0, UINT32_MAX]. However, jsid can only hold an integer in the range
* [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of
* integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be
* the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most
* cases when creating a jsid, code does not have to care about this corner
* case because:
*
* - When given an arbitrary JSAtom*, AtomToId must be used, which checks for
* integer atoms representable as integer jsids, and does this conversion.
*
* - When given a PropertyName*, NameToId can be used which which does not need
* to do any dynamic checks.
*
* Thus, it is only the rare third case which needs this function, which
* handles any JSAtom* that is known not to be representable with an int jsid.
*/
static JS_ALWAYS_INLINE jsid
ATOM_TO_JSID(JSAtom *atom)
NON_INTEGER_ATOM_TO_JSID(JSAtom *atom)
{
JS_ASSERT(((size_t)atom & 0x7) == 0);
return JSID_FROM_BITS((size_t)atom);
jsid id = JSID_FROM_BITS((size_t)atom);
JS_ASSERT(id == INTERNED_STRING_TO_JSID(NULL, (JSString*)atom));
return id;
}
/* All strings stored in jsids are atomized. */
/* All strings stored in jsids are atomized, but are not necessarily property names. */
static JS_ALWAYS_INLINE JSBool
JSID_IS_ATOM(jsid id)
{
@ -84,7 +74,7 @@ JSID_IS_ATOM(jsid id)
static JS_ALWAYS_INLINE JSBool
JSID_IS_ATOM(jsid id, JSAtom *atom)
{
return JSID_BITS(id) == JSID_BITS(ATOM_TO_JSID(atom));
return id == JSID_FROM_BITS((size_t)atom);
}
static JS_ALWAYS_INLINE JSAtom *
@ -93,9 +83,6 @@ JSID_TO_ATOM(jsid id)
return (JSAtom *)JSID_TO_STRING(id);
}
extern jsid
js_CheckForStringIndex(jsid id);
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
@ -104,7 +91,6 @@ namespace js {
static JS_ALWAYS_INLINE JSHashNumber
HashId(jsid id)
{
JS_ASSERT(js_CheckForStringIndex(id) == id);
JSHashNumber n =
#if JS_BYTES_PER_WORD == 4
JSHashNumber(JSID_BITS(id));
@ -140,11 +126,9 @@ struct DefaultHasher<jsid>
{
typedef jsid Lookup;
static HashNumber hash(const Lookup &l) {
JS_ASSERT(l == js_CheckForStringIndex(l));
return HashNumber(JSID_BITS(l));
}
static bool match(const jsid &id, const Lookup &l) {
JS_ASSERT(l == js_CheckForStringIndex(l));
return id == l;
}
};
@ -231,7 +215,7 @@ typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
* On encodings:
*
* - Some string functions have an optional FlationCoding argument that allow
* the caller to force CESU-8 encoding handling.
* the caller to force CESU-8 encoding handling.
* - Functions that don't take a FlationCoding base their NormalEncoding
* behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw
* (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8.
@ -291,38 +275,7 @@ struct JSAtomState
#undef DEFINE_PROTOTYPE_ATOM
#undef DEFINE_KEYWORD_ATOM
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
struct {
js::PropertyName *XMLListAtom;
js::PropertyName *decodeURIAtom;
js::PropertyName *decodeURIComponentAtom;
js::PropertyName *defineGetterAtom;
js::PropertyName *defineSetterAtom;
js::PropertyName *encodeURIAtom;
js::PropertyName *encodeURIComponentAtom;
js::PropertyName *escapeAtom;
js::PropertyName *hasOwnPropertyAtom;
js::PropertyName *isFiniteAtom;
js::PropertyName *isNaNAtom;
js::PropertyName *isPrototypeOfAtom;
js::PropertyName *isXMLNameAtom;
js::PropertyName *lookupGetterAtom;
js::PropertyName *lookupSetterAtom;
js::PropertyName *parseFloatAtom;
js::PropertyName *parseIntAtom;
js::PropertyName *propertyIsEnumerableAtom;
js::PropertyName *unescapeAtom;
js::PropertyName *unevalAtom;
js::PropertyName *unwatchAtom;
js::PropertyName *watchAtom;
} lazy;
static const size_t commonAtomsOffset;
static const size_t lazyAtomsOffset;
void clearLazyAtoms() {
memset(&lazy, 0, sizeof(lazy));
}
void junkAtoms() {
#ifdef DEBUG
@ -340,7 +293,7 @@ struct JSAtomState
extern bool
AtomIsInterned(JSContext *cx, JSAtom *atom);
#define ATOM(name) cx->runtime->atomState.name##Atom
#define ATOM(name) js::HandlePropertyName::fromMarkedLocation(&cx->runtime->atomState.name##Atom)
#define COMMON_ATOM_INDEX(name) \
((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \
@ -349,10 +302,10 @@ AtomIsInterned(JSContext *cx, JSAtom *atom);
((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
/ sizeof(JSAtom*))
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
#define CLASS_ATOM(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
#define NAME_OFFSET(name) offsetof(JSAtomState, name##Atom)
#define OFFSET_TO_NAME(rt,off) (*(js::PropertyName **)((char*)&(rt)->atomState + (off)))
#define CLASS_NAME_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
#define CLASS_NAME(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
extern const char *const js_common_atom_names[];
extern const size_t js_common_atom_count;
@ -457,28 +410,29 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
#endif
inline bool
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
inline bool
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp);
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp, js::Value *vp);
namespace js {
inline JSAtom *
ToAtom(JSContext *cx, const js::Value &v);
bool
InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval,
jsid *idp, Value *vp);
inline bool
InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp)
{
Value dummy;
return InternNonIntElementId(cx, obj, idval, idp, &dummy);
}
/*
* For all unmapped atoms recorded in al, add a mapping from the atom's index
* to its address. map->length must already be set to the number of atoms in
* the list and map->vector must point to pre-allocated memory.
*/
extern void
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms);
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtr<JSAtom> *atoms);
template<XDRMode mode>
bool

View File

@ -18,7 +18,7 @@
*
* DEFINE_ATOM(id, name)
* Define an atom whose JavaScript string's value is |name|.
*
*
* DEFINE_PROTOTYPE_ATOM(id)
* Define an atom whose name is the same as one of those defined in
* jsproto.tbl. The code that processes that has already declared and
@ -30,7 +30,7 @@
* jskeyword.tbl. The code that processes that has already declared and
* defined the js_<id>_str global, so this defines only the JSAtomState
* member.
*/
*/
@ -118,8 +118,33 @@ DEFINE_ATOM(hasOwn, "hasOwn")
DEFINE_ATOM(keys, "keys")
DEFINE_ATOM(iterate, "iterate")
DEFINE_PROTOTYPE_ATOM(WeakMap)
DEFINE_ATOM(buffer, "buffer")
DEFINE_ATOM(byteLength, "byteLength")
DEFINE_ATOM(byteOffset, "byteOffset")
DEFINE_KEYWORD_ATOM(return)
DEFINE_KEYWORD_ATOM(throw)
DEFINE_ATOM(url, "url")
DEFINE_ATOM(innermost, "innermost")
DEFINE_ATOM(XMLList, "XMLList")
DEFINE_ATOM(decodeURI, "decodeURI")
DEFINE_ATOM(decodeURIComponent, "decodeURIComponent")
DEFINE_ATOM(defineGetter, "__defineGetter__")
DEFINE_ATOM(defineSetter, "__defineSetter__")
DEFINE_ATOM(encodeURI, "encodeURI")
DEFINE_ATOM(encodeURIComponent, "encodeURIComponent")
DEFINE_ATOM(escape, "escape")
DEFINE_ATOM(hasOwnProperty, "hasOwnProperty")
DEFINE_ATOM(isFinite, "isFinite")
DEFINE_ATOM(isNaN, "isNaN")
DEFINE_ATOM(isPrototypeOf, "isPrototypeOf")
DEFINE_ATOM(isXMLName, "isXMLName")
DEFINE_ATOM(lookupGetter, "__lookupGetter__")
DEFINE_ATOM(lookupSetter, "__lookupSetter__")
DEFINE_ATOM(parseFloat, "parseFloat")
DEFINE_ATOM(parseInt, "parseInt")
DEFINE_ATOM(propertyIsEnumerable, "propertyIsEnumerable")
DEFINE_ATOM(unescape, "unescape")
DEFINE_ATOM(uneval, "uneval")
DEFINE_ATOM(unwatch, "unwatch")
DEFINE_ATOM(watch, "watch")

View File

@ -1,119 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Gregor Wagner <anygregor@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef jscell_h___
#define jscell_h___
#include "jspubtd.h"
struct JSCompartment;
namespace js {
namespace gc {
struct ArenaHeader;
struct Chunk;
/* The GC allocation kinds. */
enum AllocKind {
FINALIZE_OBJECT0,
FINALIZE_OBJECT0_BACKGROUND,
FINALIZE_OBJECT2,
FINALIZE_OBJECT2_BACKGROUND,
FINALIZE_OBJECT4,
FINALIZE_OBJECT4_BACKGROUND,
FINALIZE_OBJECT8,
FINALIZE_OBJECT8_BACKGROUND,
FINALIZE_OBJECT12,
FINALIZE_OBJECT12_BACKGROUND,
FINALIZE_OBJECT16,
FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
FINALIZE_SCRIPT,
FINALIZE_SHAPE,
FINALIZE_BASE_SHAPE,
FINALIZE_TYPE_OBJECT,
#if JS_HAS_XML_SUPPORT
FINALIZE_XML,
#endif
FINALIZE_SHORT_STRING,
FINALIZE_STRING,
FINALIZE_EXTERNAL_STRING,
FINALIZE_LAST = FINALIZE_EXTERNAL_STRING
};
static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1;
static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1;
/*
* Live objects are marked black. How many other additional colors are available
* depends on the size of the GCThing. Objects marked gray are eligible for
* cycle collection.
*/
static const uint32_t BLACK = 0;
static const uint32_t GRAY = 1;
/*
* A GC cell is the base class for all GC things.
*/
struct Cell {
static const size_t CellShift = 3;
static const size_t CellSize = size_t(1) << CellShift;
static const size_t CellMask = CellSize - 1;
inline uintptr_t address() const;
inline ArenaHeader *arenaHeader() const;
inline Chunk *chunk() const;
inline AllocKind getAllocKind() const;
JS_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
JS_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
JS_ALWAYS_INLINE void unmark(uint32_t color) const;
inline JSCompartment *compartment() const;
#ifdef DEBUG
inline bool isAligned() const;
#endif
};
} /* namespace gc */
} /* namespace js */
#endif /* jscell_h___ */

View File

@ -1,41 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey JavaScript engine.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsclass_h__
#define jsclass_h__
@ -54,6 +22,7 @@ namespace js {
class PropertyName;
class SpecialId;
class PropertyId;
static JS_ALWAYS_INLINE jsid
SPECIALID_TO_JSID(const SpecialId &sid);
@ -69,12 +38,13 @@ SPECIALID_TO_JSID(const SpecialId &sid);
* does not occur in JS scripts but may be used to indicate the absence of a
* valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
*/
class SpecialId {
class SpecialId
{
uintptr_t bits;
/* Needs access to raw bits. */
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
friend class PropertyId;
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
@ -174,83 +144,75 @@ JSID_TO_SPECIALID(jsid id)
return SpecialId::defaultXMLNamespace();
}
typedef JS::Handle<SpecialId> HandleSpecialId;
/* js::Class operation signatures. */
typedef JSBool
(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
JSProperty **propp);
(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
typedef JSBool
(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
JSProperty **propp);
(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleObject objp, MutableHandleShape propp);
typedef JSBool
(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
JSProperty **propp);
(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp);
typedef JSBool
(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
JSProperty **propp);
(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, MutableHandleShape propp);
typedef JSBool
(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
typedef JSBool
(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
typedef JSBool
(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
typedef JSBool
(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
typedef JSBool
(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp);
typedef JSBool
(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp);
typedef JSBool
(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp);
typedef JSBool
(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present);
(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool* present);
typedef JSBool
(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp);
typedef JSBool
(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict);
typedef JSBool
(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
typedef JSBool
(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
typedef JSBool
(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
typedef JSBool
(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
typedef JSBool
(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp);
typedef JSBool
(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
typedef JSBool
(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
typedef JSBool
(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
typedef JSBool
(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
typedef JSBool
(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
typedef JSType
(* TypeOfOp)(JSContext *cx, JSObject *obj);
/*
* Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
* On error, return false.
* If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
* If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
* caller will throw an appropriate error.
*/
typedef JSBool
(* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props);
(* TypeOfOp)(JSContext *cx, HandleObject obj);
typedef JSObject *
(* ObjectOp)(JSContext *cx, JSObject *obj);
(* ObjectOp)(JSContext *cx, HandleObject obj);
typedef void
(* ClearOp)(JSContext *cx, HandleObject obj);
typedef void
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
typedef void
(* ClearOp)(JSContext *cx, JSObject *obj);
#define JS_CLASS_MEMBERS \
const char *name; \
@ -269,8 +231,8 @@ typedef void
/* Optionally non-null members start here. */ \
JSCheckAccessOp checkAccess; \
JSNative call; \
JSNative construct; \
JSHasInstanceOp hasInstance; \
JSNative construct; \
JSTraceOp trace
/*
@ -332,7 +294,6 @@ struct ObjectOps
JSNewEnumerateOp enumerate;
TypeOfOp typeOf;
FixOp fix;
ObjectOp thisObject;
ClearOp clear;
};
@ -340,7 +301,7 @@ struct ObjectOps
#define JS_NULL_OBJECT_OPS \
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
NULL,NULL,NULL,NULL,NULL,NULL}
NULL,NULL,NULL,NULL,NULL}
struct Class
{
@ -406,7 +367,8 @@ Valueify(const JSClass *c)
* value of objects.
*/
enum ESClassValue {
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean,
ESClass_RegExp, ESClass_ArrayBuffer
};
/*
@ -424,6 +386,25 @@ IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
} /* namespace js */
namespace JS {
inline bool
IsPoisonedSpecialId(js::SpecialId iden)
{
if (iden.isObject())
return IsPoisonedPtr(iden.toObject());
return false;
}
template <> struct RootMethods<js::SpecialId>
{
static js::SpecialId initial() { return js::SpecialId(); }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(js::SpecialId id) { return IsPoisonedSpecialId(id); }
};
} /* namespace JS */
#endif /* __cplusplus */
#endif /* jsclass_h__ */

View File

@ -1,40 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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 jsclist_h___
#define jsclist_h___

View File

@ -1,41 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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_cpucfg___
#define js_cpucfg___

View File

@ -1,43 +1,9 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Nick Fitzgerald <nfitzgerald@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsdbgapi_h___
#define jsdbgapi_h___
@ -120,6 +86,13 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug);
extern JS_PUBLIC_API(JSBool)
JS_GetDebugMode(JSContext *cx);
/*
* Turn on/off debugging mode for all compartments. This returns false if any code
* from any of the runtime's compartments is running or on the stack.
*/
JS_FRIEND_API(JSBool)
JS_SetDebugModeForAllCompartments(JSContext *cx, JSBool debug);
/*
* Turn on/off debugging mode for a single compartment. This should only be
* used when no code from this compartment is running or on the stack in any
@ -248,6 +221,9 @@ JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
extern JS_PUBLIC_API(void)
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
extern JS_PUBLIC_API(JSPrincipals*)
JS_GetPrincipalIfDummyFrame(JSContext *cx, JSStackFrame *fpArg);
extern JS_PUBLIC_API(JSBool)
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
@ -299,6 +275,17 @@ JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
/************************************************************************/
/*
* This is almost JS_GetClass(obj)->name except that certain debug-only
* proxies are made transparent. In particular, this function turns the class
* of any scope (returned via JS_GetFrameScopeChain or JS_GetFrameCalleeObject)
* from "Proxy" to "Call", "Block", "With" etc.
*/
extern JS_PUBLIC_API(const char *)
JS_GetDebugClassName(JSObject *obj);
/************************************************************************/
extern JS_PUBLIC_API(const char *)
JS_GetScriptFilename(JSContext *cx, JSScript *script);
@ -352,7 +339,6 @@ typedef struct JSPropertyDesc {
jsval value; /* property value */
uint8_t flags; /* flags, see below */
uint8_t spare; /* unused */
uint16_t slot; /* argument/variable slot */
jsval alias; /* alias id if JSPD_ALIAS flag */
} JSPropertyDesc;
@ -360,8 +346,6 @@ typedef struct JSPropertyDesc {
#define JSPD_READONLY 0x02 /* assignment is error */
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
#define JSPD_ALIAS 0x08 /* property has an alias id */
#define JSPD_ARGUMENT 0x10 /* argument to function */
#define JSPD_VARIABLE 0x20 /* local variable in function */
#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
/* value is exception */
#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
@ -374,13 +358,6 @@ typedef struct JSPropertyDescArray {
typedef struct JSScopeProperty JSScopeProperty;
extern JS_PUBLIC_API(JSScopeProperty *)
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
extern JS_PUBLIC_API(JSBool)
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *shape,
JSPropertyDesc *pd);
extern JS_PUBLIC_API(JSBool)
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
@ -418,23 +395,6 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
extern JS_PUBLIC_API(size_t)
JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
/*
* Return true if obj is a "system" object, that is, one created by
* JS_NewSystemObject with the system flag set and not JS_NewObject.
*
* What "system" means is up to the API client.
*/
extern JS_PUBLIC_API(JSBool)
JS_IsSystemObject(JSContext *cx, JSObject *obj);
/*
* Mark an object as being a system object. This should be called immediately
* after allocating the object. A system object is an object for which
* JS_IsSystemObject returns true.
*/
extern JS_PUBLIC_API(JSBool)
JS_MakeSystemObject(JSContext *cx, JSObject *obj);
/************************************************************************/
extern JS_FRIEND_API(void)
@ -532,6 +492,16 @@ js_ResumeVtune();
#endif /* MOZ_VTUNE */
#ifdef __linux__
extern JS_FRIEND_API(JSBool)
js_StartPerf();
extern JS_FRIEND_API(JSBool)
js_StopPerf();
#endif /* __linux__ */
extern JS_PUBLIC_API(void)
JS_DumpBytecode(JSContext *cx, JSScript *script);
@ -547,6 +517,9 @@ JS_DumpCompartmentPCCounts(JSContext *cx);
extern JS_PUBLIC_API(JSObject *)
JS_UnwrapObject(JSObject *obj);
extern JS_PUBLIC_API(JSObject *)
JS_UnwrapObjectAndInnerize(JSObject *obj);
/* Call the context debug handler on the topmost scripted frame. */
extern JS_FRIEND_API(JSBool)
js_CallContextDebugHandler(JSContext *cx);

View File

@ -1,40 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla JavaScript code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999-2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brendan Eich <brendan@mozilla.org> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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 jsdhash_h___
#define jsdhash_h___

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
*
* The Original Code is SpiderMonkey code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsfriendapi_h___
#define jsfriendapi_h___
@ -87,6 +54,15 @@ JS_GetCustomIteratorCount(JSContext *cx);
extern JS_FRIEND_API(JSBool)
JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret);
/*
* Determine whether the given object is backed by a DeadObjectProxy.
*
* Such objects hold no other objects (they have no outgoing reference edges)
* and will throw if you touch them (e.g. by reading/writing a property).
*/
extern JS_FRIEND_API(JSBool)
JS_IsDeadWrapper(JSObject *obj);
/*
* Used by the cycle collector to trace through the shape and all
* shapes it reaches, marking all non-shape children found in the
@ -117,6 +93,9 @@ JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallba
extern JS_FRIEND_API(JSPrincipals *)
JS_GetCompartmentPrincipals(JSCompartment *compartment);
extern JS_FRIEND_API(void)
JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals);
/* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */
extern JS_FRIEND_API(JSObject *)
JS_ObjectToInnerObject(JSContext *cx, JSObject *obj);
@ -129,7 +108,7 @@ extern JS_FRIEND_API(JSObject *)
JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
extern JS_FRIEND_API(JSBool)
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
JS_FRIEND_API(void)
js_ReportOverRecursed(JSContext *maybecx);
@ -164,7 +143,10 @@ extern JS_FRIEND_API(JSBool)
JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
extern JS_FRIEND_API(JSBool)
JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
JS_WrapAutoIdVector(JSContext *cx, JS::AutoIdVector &props);
extern JS_FRIEND_API(JSBool)
JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
struct JSFunctionSpecWithHelp {
const char *name;
@ -217,26 +199,13 @@ GetRuntime(const JSContext *cx)
typedef bool
(* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
#ifdef DEBUG
/*
* DEBUG-only method to dump the complete object graph of heap-allocated things.
* Dump the complete object graph of heap-allocated things.
* fp is the file for the dump output.
*/
extern JS_FRIEND_API(void)
DumpHeapComplete(JSRuntime *rt, FILE *fp);
#endif
class JS_FRIEND_API(AutoPreserveCompartment) {
private:
JSContext *cx;
JSCompartment *oldCompartment;
public:
AutoPreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoPreserveCompartment();
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class JS_FRIEND_API(AutoSwitchCompartment) {
private:
JSContext *cx;
@ -296,6 +265,15 @@ TraceWeakMaps(WeakMapTracer *trc);
extern JS_FRIEND_API(bool)
GCThingIsMarkedGray(void *thing);
extern JS_FRIEND_API(JSCompartment*)
GetGCThingCompartment(void *thing);
typedef void
(GCThingCallback)(void *closure, void *gcthing);
extern JS_FRIEND_API(void)
VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure);
/*
* Shadow declarations of JS internal structures, for access by inline access
* functions below. Do not use these structures in any other way. When adding
@ -388,6 +366,9 @@ GetObjectParentMaybeScope(JSObject *obj);
JS_FRIEND_API(JSObject *)
GetGlobalForObjectCrossCompartment(JSObject *obj);
JS_FRIEND_API(void)
NotifyAnimationActivity(JSObject *obj);
JS_FRIEND_API(bool)
IsOriginalScriptFunction(JSFunction *fun);
@ -498,6 +479,9 @@ CastAsJSStrictPropertyOp(JSObject *object)
JS_FRIEND_API(bool)
GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props);
JS_FRIEND_API(bool)
GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
JS_FRIEND_API(bool)
StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
@ -552,6 +536,34 @@ GetPCCountScriptSummary(JSContext *cx, size_t script);
JS_FRIEND_API(JSString *)
GetPCCountScriptContents(JSContext *cx, size_t script);
/*
* A call stack can be specified to the JS engine such that all JS entry/exits
* to functions push/pop an entry to/from the specified stack.
*
* For more detailed information, see vm/SPSProfiler.h
*/
struct ProfileEntry {
/*
* These two fields are marked as 'volatile' so that the compiler doesn't
* re-order instructions which modify them. The operation in question is:
*
* stack[i].string = str;
* (*size)++;
*
* If the size increment were re-ordered before the store of the string,
* then if sampling occurred there would be a bogus entry on the stack.
*/
const char * volatile string;
void * volatile sp;
};
JS_FRIEND_API(void)
SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size,
uint32_t max);
JS_FRIEND_API(void)
EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled);
#ifdef JS_THREADSAFE
JS_FRIEND_API(void *)
GetOwnerThread(const JSContext *cx);
@ -581,7 +593,7 @@ extern JS_FRIEND_API(const JSStructuredCloneCallbacks *)
GetContextStructuredCloneCallbacks(JSContext *cx);
extern JS_FRIEND_API(JSVersion)
VersionSetXML(JSVersion version, bool enable);
VersionSetMoarXML(JSVersion version, bool enable);
extern JS_FRIEND_API(bool)
CanCallContextDebugHandler(JSContext *cx);
@ -610,8 +622,8 @@ SizeOfJSContext();
D(TOO_MUCH_MALLOC) \
D(ALLOC_TRIGGER) \
D(DEBUG_GC) \
D(UNUSED2) /* was SHAPE */ \
D(UNUSED3) /* was REFILL */ \
D(DEBUG_MODE_GC) \
D(TRANSPLANT) \
\
/* Reasons from Firefox */ \
D(DOM_WINDOW_UTILS) \
@ -629,7 +641,9 @@ SizeOfJSContext();
D(DOM_IPC) \
D(DOM_WORKER) \
D(INTER_SLICE_GC) \
D(REFRESH_FRAME)
D(REFRESH_FRAME) \
D(FULL_GC_TIMER) \
D(SHUTDOWN_CC)
namespace gcreason {
@ -639,7 +653,15 @@ enum Reason {
GCREASONS(MAKE_REASON)
#undef MAKE_REASON
NO_REASON,
NUM_REASONS
NUM_REASONS,
/*
* For telemetry, we want to keep a fixed max bucket size over time so we
* don't have to switch histograms. 100 is conservative; as of this writing
* there are 26. But the cost of extra buckets seems to be low while the
* cost of switching histograms is high.
*/
NUM_TELEMETRY_REASONS = 100
};
} /* namespace gcreason */
@ -650,6 +672,15 @@ PrepareCompartmentForGC(JSCompartment *comp);
extern JS_FRIEND_API(void)
PrepareForFullGC(JSRuntime *rt);
extern JS_FRIEND_API(void)
PrepareForIncrementalGC(JSRuntime *rt);
extern JS_FRIEND_API(bool)
IsGCScheduled(JSRuntime *rt);
extern JS_FRIEND_API(void)
SkipCompartmentForGC(JSCompartment *comp);
/*
* When triggering a GC using one of the functions below, it is first necessary
* to select the compartments to be collected. To do this, you can call
@ -667,7 +698,7 @@ extern JS_FRIEND_API(void)
IncrementalGC(JSRuntime *rt, gcreason::Reason reason);
extern JS_FRIEND_API(void)
SetGCSliceTimeBudget(JSContext *cx, int64_t millis);
FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason);
enum GCProgress {
/*
@ -724,12 +755,18 @@ IsIncrementalBarrierNeeded(JSContext *cx);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeededOnObject(JSObject *obj);
extern JS_FRIEND_API(bool)
IsIncrementalBarrierNeededOnScript(JSScript *obj);
extern JS_FRIEND_API(void)
IncrementalReferenceBarrier(void *ptr);
extern JS_FRIEND_API(void)
IncrementalValueBarrier(const Value &v);
extern JS_FRIEND_API(void)
PokeGC(JSRuntime *rt);
class ObjectPtr
{
JSObject *value;
@ -790,6 +827,16 @@ CastToJSFreeOp(FreeOp *fop)
extern JS_FRIEND_API(const jschar*)
GetErrorTypeNameFromNumber(JSContext* cx, const unsigned errorNumber);
/* Implemented in jswrapper.cpp. */
typedef enum NukedGlobalHandling {
NukeForGlobalObject,
DontNukeForGlobalObject
} NukedGlobalHandling;
extern JS_FRIEND_API(JSBool)
NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj,
NukedGlobalHandling nukeGlobal);
} /* namespace js */
#endif
@ -963,6 +1010,16 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes);
extern JS_FRIEND_API(JSBool)
JS_IsTypedArrayObject(JSObject *obj, JSContext *cx);
/*
* 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.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
/*
* Test for specific typed array types (ArrayBufferView subtypes)
*/
@ -1063,6 +1120,14 @@ JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(uint32_t)
JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx);
/*
* Check whether obj supports JS_ArrayBufferView* APIs. Note that this may
* return false if a security wrapper is encountered that denies the
* unwrapping.
*/
extern JS_FRIEND_API(JSBool)
JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx);
/*
* More generic name for JS_GetTypedArrayByteLength to cover DataViews as well
*/
@ -1106,4 +1171,46 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx);
extern JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx);
/*
* 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.
*/
JS_FRIEND_API(JSBool)
JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView);
/*
* Return the byte offset of a data view into its array buffer. |obj| must be a
* DataView.
*
* |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.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteOffset(JSObject *obj, JSContext *cx);
/*
* Return the byte length of a data view.
*
* |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.
*/
JS_FRIEND_API(uint32_t)
JS_GetDataViewByteLength(JSObject *obj, JSContext *cx);
/*
* Return a pointer to the beginning of the data referenced by a DataView.
*
* |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.
*/
JS_FRIEND_API(void *)
JS_GetDataViewData(JSObject *obj, JSContext *cx);
#endif /* jsfriendapi_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jshash_h___
#define jshash_h___

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jslock_h__
#define jslock_h__
@ -56,6 +23,10 @@
#else /* JS_THREADSAFE */
typedef struct PRThread PRThread;
typedef struct PRCondVar PRCondVar;
typedef struct PRLock PRLock;
# define JS_ATOMIC_INCREMENT(p) (++*(p))
# define JS_ATOMIC_DECREMENT(p) (--*(p))
# define JS_ATOMIC_ADD(p,v) (*(p) += (v))

View File

@ -1,39 +1,6 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey JSON.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Sayre <sayrer@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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 json_h___
#define json_h___
@ -50,9 +17,14 @@ extern JSObject *
js_InitJSONClass(JSContext *cx, JSObject *obj);
extern JSBool
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
js_Stringify(JSContext *cx, js::MutableHandleValue vp,
JSObject *replacer, js::Value space,
js::StringBuffer &sb);
// Avoid build errors on certain platforms that define these names as constants
#undef STRICT
#undef LEGACY
/*
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the

View File

@ -1,40 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Zack Weinberg <zweinberg@mozilla.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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 jsperf_h___
#define jsperf_h___

View File

@ -1,40 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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 jsprf_h___
#define jsprf_h___

View File

@ -1,40 +1,9 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set sw=4 ts=8 et tw=80 ft=c:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is SpiderMonkey 1.7 work in progress, released
* February 14, 2006.
*
* The Initial Developer of the Original Code is
* Brendan Eich <brendan@mozilla.org>
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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/. */
#include "jsversion.h"
@ -94,6 +63,7 @@ JS_PROTO(AnyName, 35, js_InitNullClass)
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
JS_PROTO(Map, 37, js_InitMapClass)
JS_PROTO(Set, 38, js_InitSetClass)
JS_PROTO(DataView, 39, js_InitTypedArrayClasses)
#undef XML_INIT
#undef NAMESPACE_INIT

View File

@ -1,43 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsproxy_h___
#define jsproxy_h___
@ -47,33 +13,91 @@
namespace js {
/* Base class for all C++ proxy handlers. */
class JS_FRIEND_API(ProxyHandler) {
class Wrapper;
/*
* A proxy is a JSObject that implements generic behavior by providing custom
* implementations for each object trap. The implementation for each trap is
* provided by a C++ object stored on the proxy, known as its handler.
*
* A major use case for proxies is to forward each trap to another object,
* known as its target. The target can be an arbitrary C++ object. Not every
* proxy has the notion of a target, however.
*
* 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.
*
* To minimize code duplication, a set of abstract proxy handler classes is
* provided, from which other handlers may inherit. These abstract classes
* are organized in the following hierarchy:
*
* BaseProxyHandler
* |
* IndirectProxyHandler
* |
* DirectProxyHandler
*/
/*
* BaseProxyHandler is the most generic kind of proxy handler. It does not make
* any assumptions about the target. Consequently, it does not provide any
* default implementation for the fundamental traps. It does, however, implement
* the derived traps in terms of the fundamental ones. This allows consumers of
* this class to define any custom behavior they want.
*/
class JS_FRIEND_API(BaseProxyHandler) {
void *mFamily;
public:
explicit ProxyHandler(void *family);
virtual ~ProxyHandler();
explicit BaseProxyHandler(void *family);
virtual ~BaseProxyHandler();
inline void *family() {
return mFamily;
}
virtual bool isOuterWindow() {
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;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
bool set, PropertyDescriptor *desc) = 0;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
jsid id, bool set,
PropertyDescriptor *desc) = 0;
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
PropertyDescriptor *desc) = 0;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy,
AutoIdVector &props) = 0;
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
virtual bool enumerate(JSContext *cx, JSObject *proxy,
AutoIdVector &props) = 0;
/* ES5 Harmony derived proxy traps. */
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
Value *vp);
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, Value *vp);
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver,
jsid id, bool strict, Value *vp);
virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp);
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags,
Value *vp);
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
@ -88,17 +112,87 @@ class JS_FRIEND_API(ProxyHandler) {
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
virtual void trace(JSTracer *trc, JSObject *proxy);
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
uint32_t index, Value *vp, bool *present);
};
virtual bool isOuterWindow() {
return false;
}
/*
* 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.
*/
class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler {
public:
explicit IndirectProxyHandler(void *family);
inline void *family() {
return mFamily;
}
/* ES5 Harmony fundamental proxy traps. */
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id,
bool set,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
jsid id, bool set,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
PropertyDescriptor *desc) MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id,
bool *bp) MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JSObject *proxy,
AutoIdVector &props) MOZ_OVERRIDE;
/* Spidermonkey extensions. */
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc,
Value *vp) MOZ_OVERRIDE;
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc,
Value *argv, Value *rval) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp,
Native native, CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp,
bool *bp) MOZ_OVERRIDE;
virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue,
JSContext *cx) MOZ_OVERRIDE;
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy,
unsigned indent) MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy,
RegExpGuard *g) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint,
Value *vp) MOZ_OVERRIDE;
virtual bool iteratorNext(JSContext *cx, JSObject *proxy,
Value *vp) MOZ_OVERRIDE;
};
/*
* 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. */
@ -117,7 +211,6 @@ class Proxy {
static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
static bool fix(JSContext *cx, JSObject *proxy, Value *vp);
/* ES5 Harmony derived proxy traps. */
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
@ -178,11 +271,11 @@ const uint32_t JSSLOT_PROXY_EXTRA = 2;
const uint32_t JSSLOT_PROXY_CALL = 4;
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
inline ProxyHandler *
inline BaseProxyHandler *
GetProxyHandler(const JSObject *obj)
{
JS_ASSERT(IsProxy(obj));
return (ProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
}
inline const Value &
@ -192,6 +285,20 @@ GetProxyPrivate(const JSObject *obj)
return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
}
inline JSObject *
GetProxyTargetObject(const JSObject *obj)
{
JS_ASSERT(IsProxy(obj));
return GetProxyPrivate(obj).toObjectOrNull();
}
inline const Value &
GetProxyCall(const JSObject *obj)
{
JS_ASSERT(IsFunctionProxy(obj));
return GetReservedSlot(obj, JSSLOT_PROXY_CALL);
}
inline const Value &
GetProxyExtra(const JSObject *obj, size_t n)
{
@ -200,16 +307,7 @@ GetProxyExtra(const JSObject *obj, size_t n)
}
inline void
SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
{
JS_ASSERT(IsProxy(obj));
JS_ASSERT(n <= 1);
SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
}
inline void
SetProxyHandler(JSObject *obj, ProxyHandler *handler)
SetProxyHandler(JSObject *obj, BaseProxyHandler *handler)
{
JS_ASSERT(IsProxy(obj));
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
@ -222,8 +320,16 @@ SetProxyPrivate(JSObject *obj, const Value &value)
SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value);
}
inline void
SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
{
JS_ASSERT(IsProxy(obj));
JS_ASSERT(n <= 1);
SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
}
JS_FRIEND_API(JSObject *)
NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv,
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
JSObject *proto, JSObject *parent,
JSObject *call = NULL, JSObject *construct = NULL);

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsprvtd_h___
#define jsprvtd_h___
@ -84,7 +51,6 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap;
typedef struct JSGCThing JSGCThing;
typedef struct JSGenerator JSGenerator;
typedef struct JSNativeEnumerator JSNativeEnumerator;
typedef struct JSProperty JSProperty;
typedef struct JSSharpObjectMap JSSharpObjectMap;
typedef struct JSTryNote JSTryNote;
@ -95,7 +61,10 @@ typedef struct JSPrinter JSPrinter;
typedef struct JSStackHeader JSStackHeader;
typedef struct JSSubString JSSubString;
typedef struct JSSpecializedNative JSSpecializedNative;
#if JS_HAS_XML_SUPPORT
typedef struct JSXML JSXML;
#endif
/*
* Template declarations.
@ -160,9 +129,7 @@ class StackFrame;
class StackSegment;
class StackSpace;
class ContextStack;
class FrameRegsIter;
class CallReceiver;
class CallArgs;
class ScriptFrameIter;
struct BytecodeEmitter;
struct Definition;
@ -170,6 +137,7 @@ struct FunctionBox;
struct ObjectBox;
struct ParseNode;
struct Parser;
struct SharedContext;
class TokenStream;
struct Token;
struct TokenPos;
@ -178,8 +146,8 @@ struct TreeContext;
class UpvarCookie;
class Proxy;
class ProxyHandler;
class Wrapper;
class BaseProxyHandler;
class DirectWrapper;
class CrossCompartmentWrapper;
class TempAllocPolicy;
@ -206,10 +174,9 @@ struct StackShape;
class MultiDeclRange;
class ParseMapPool;
class DefnOrHeader;
class DefinitionList;
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
typedef Vector<UpvarCookie, 8> UpvarCookies;
class Breakpoint;
@ -256,17 +223,13 @@ typedef JS::Handle<types::TypeObject*> HandleTypeObject;
typedef JS::Handle<JSAtom*> HandleAtom;
typedef JS::Handle<PropertyName*> HandlePropertyName;
typedef JS::Root<Shape*> RootShape;
typedef JS::Root<BaseShape*> RootBaseShape;
typedef JS::Root<types::TypeObject*> RootTypeObject;
typedef JS::Root<JSAtom*> RootAtom;
typedef JS::Root<PropertyName*> RootPropertyName;
typedef JS::MutableHandle<Shape*> MutableHandleShape;
typedef JS::RootedVar<Shape*> RootedVarShape;
typedef JS::RootedVar<BaseShape*> RootedVarBaseShape;
typedef JS::RootedVar<types::TypeObject*> RootedVarTypeObject;
typedef JS::RootedVar<JSAtom*> RootedVarAtom;
typedef JS::RootedVar<PropertyName*> RootedVarPropertyName;
typedef JS::Rooted<Shape*> RootedShape;
typedef JS::Rooted<BaseShape*> RootedBaseShape;
typedef JS::Rooted<types::TypeObject*> RootedTypeObject;
typedef JS::Rooted<JSAtom*> RootedAtom;
typedef JS::Rooted<PropertyName*> RootedPropertyName;
enum XDRMode {
XDR_ENCODE,
@ -404,41 +367,23 @@ typedef struct JSDebugHooks {
/* js::ObjectOps function pointer typedefs. */
/*
* Look for id in obj and its prototype chain, returning false on error or
* exception, true on success. On success, return null in *propp if id was
* not found. If id was found, return the first object searching from obj
* along its prototype chain in which id names a direct property in *objp, and
* return a non-null, opaque property pointer in *propp.
*
* If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
* may be passed as the prop parameter to a JSAttributesOp, as a short-cut
* that bypasses id re-lookup.
*/
typedef JSBool
(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
JSProperty **propp);
/*
* Get or set attributes of the property obj[id]. Return false on error or
* exception, true with current attributes in *attrsp.
*/
typedef JSBool
(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
/*
* A generic type for functions mapping an object to another object, or null
* if an error or exception was thrown on cx.
*/
typedef JSObject *
(* JSObjectOp)(JSContext *cx, JSObject *obj);
(* JSObjectOp)(JSContext *cx, JSHandleObject obj);
/* Signature for class initialization ops. */
typedef JSObject *
(* JSClassInitializerOp)(JSContext *cx, JSObject *obj);
/*
* Hook that creates an iterator object for a given object. Returns the
* iterator object or null if an error or exception was thrown on cx.
*/
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
/*
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes

View File

@ -1,41 +1,8 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jspubtd_h___
#define jspubtd_h___
@ -148,7 +115,11 @@ typedef enum JSProtoKey {
/* js_CheckAccess mode enumeration. */
typedef enum JSAccessMode {
JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */
/*
* enum value #1 formerly called JSACC_PARENT,
* gap preserved for ABI compatibility.
*/
/*
* enum value #2 formerly called JSACC_IMPORT,
@ -249,7 +220,7 @@ JS_END_EXTERN_C
namespace JS {
template <typename T>
class Root;
class Rooted;
class SkipRoot;
@ -261,8 +232,11 @@ enum ThingRootKind
THING_ROOT_TYPE_OBJECT,
THING_ROOT_STRING,
THING_ROOT_SCRIPT,
THING_ROOT_XML,
THING_ROOT_ID,
THING_ROOT_PROPERTY_ID,
THING_ROOT_VALUE,
THING_ROOT_TYPE,
THING_ROOT_LIMIT
};
@ -280,15 +254,15 @@ struct ContextFriendFields {
return reinterpret_cast<ContextFriendFields *>(cx);
}
#ifdef JSGC_ROOT_ANALYSIS
#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.
*/
Root<void*> *thingGCRooters[THING_ROOT_LIMIT];
Rooted<void*> *thingGCRooters[THING_ROOT_LIMIT];
#endif
#ifdef DEBUG
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
/*
* Stack allocated list of stack locations which hold non-relocatable
* GC heap pointers (where the target is rooted somewhere else) or integer
@ -299,8 +273,6 @@ struct ContextFriendFields {
*/
SkipRoot *skipGCRooters;
#endif
#endif /* JSGC_ROOT_ANALYSIS */
};
} /* namespace JS */

View File

@ -1,41 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* IBM Corp.
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* 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/. */
/*
** File: jstypes.h

View File

@ -1,41 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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/. */
/*
* PR assertion checker.
@ -410,14 +377,8 @@ inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
#endif
#ifdef JS_CRASH_DIAGNOSTICS
# define JS_POISON(p, val, size) memset((p), (val), (size))
# define JS_OPT_ASSERT(expr) \
((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
# define JS_OPT_ASSERT_IF(cond, expr) \
((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
#else
# define JS_POISON(p, val, size) ((void) 0)
# define JS_OPT_ASSERT(expr) ((void) 0)
# define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
#endif
/* Basic stats */

View File

@ -1,41 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* June 30, 2010
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
* Luke Wagner <lw@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jsvalimpl_h__
#define jsvalimpl_h__
@ -44,8 +12,6 @@
* Implementation details for js::Value in jsapi.h.
*/
#include "mozilla/FloatingPoint.h"
#include "js/Utility.h"
JS_BEGIN_EXTERN_C
@ -247,10 +213,11 @@ typedef enum JSWhyMagic
JS_ARG_POISON, /* used in debug builds to catch tracing errors */
JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
JS_UNASSIGNED_ARGUMENTS, /* the initial value of callobj.arguments */
JS_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
JS_FORWARD_TO_CALL_OBJECT, /* args object element stored in call object */
JS_BLOCK_NEEDS_CLONE, /* value of static block object slot */
JS_GENERIC_MAGIC /* for local use */
} JSWhyMagic;
@ -269,6 +236,7 @@ typedef union jsval_layout
void *ptr;
JSWhyMagic why;
size_t word;
uintptr_t uintptr;
} payload;
JSValueTag tag;
} s;
@ -296,6 +264,7 @@ typedef union jsval_layout
double asDouble;
void *asPtr;
size_t asWord;
uintptr_t asUIntPtr;
} JSVAL_ALIGNMENT jsval_layout;
# endif /* JS_BITS_PER_WORD */
#else /* defined(IS_LITTLE_ENDIAN) */
@ -314,6 +283,7 @@ typedef union jsval_layout
void *ptr;
JSWhyMagic why;
size_t word;
uintptr_t uintptr;
} payload;
} s;
double asDouble;
@ -338,6 +308,7 @@ typedef union jsval_layout
double asDouble;
void *asPtr;
size_t asWord;
uintptr_t asUIntPtr;
} JSVAL_ALIGNMENT jsval_layout;
# endif /* JS_BITS_PER_WORD */
#endif /* defined(IS_LITTLE_ENDIAN) */

View File

@ -1,41 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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/. */
/*
* JS configuration macros.
@ -91,7 +58,6 @@
#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */
#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
@ -113,7 +79,6 @@
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
@ -131,7 +96,6 @@
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
@ -149,7 +113,6 @@
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
@ -167,7 +130,6 @@
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */

View File

@ -1,43 +1,9 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Andreas Gal <gal@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
* 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 jswrapper_h___
#define jswrapper_h___
@ -51,30 +17,76 @@ namespace js {
class DummyFrameGuard;
/* Base class that just implements no-op forwarding methods for fundamental
* traps. This is meant to be used as a base class for ProxyHandlers that
* want transparent forwarding behavior but don't want to use the derived
* traps and other baggage of js::Wrapper.
/*
* 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
*/
class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
class JS_FRIEND_API(Wrapper)
{
unsigned mFlags;
public:
unsigned flags() const { return mFlags; }
enum Action {
GET,
SET,
CALL,
PUNCTURE
};
explicit AbstractWrapper(unsigned flags);
enum Flags {
CROSS_COMPARTMENT = 1 << 0,
LAST_USED_FLAG = CROSS_COMPARTMENT
};
/* 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;
virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
typedef enum {
PermitObjectAccess,
PermitPropertyAccess,
DenyAccess
} Permission;
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
JSObject *parent, Wrapper *handler);
static Wrapper *wrapperHandler(const JSObject *wrapper);
static JSObject *wrappedObject(const JSObject *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.
*
@ -82,12 +94,9 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
* on the underlying object's |id| property. In the case when |act| is CALL,
* |id| is generally JSID_VOID.
*
* leave() allows the policy to undo various scoped state changes taken in
* enter(). If enter() succeeds, leave() must be called upon completion of
* the approved action.
*
* The |act| parameter to enter() specifies the action being performed. GET,
* SET, and CALL are self-explanatory, but PUNCTURE requires more explanation:
* 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
@ -103,24 +112,87 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
* permission, and thus should generally be denied for security wrappers
* except under very special circumstances. When |act| is PUNCTURE, |id|
* should be JSID_VOID.
* */
enum Action { GET, SET, CALL, PUNCTURE };
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
virtual void leave(JSContext *cx, JSObject *wrapper);
static JSObject *wrappedObject(const JSObject *wrapper);
static AbstractWrapper *wrapperHandler(const JSObject *wrapper);
*/
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act,
bool *bp);
};
/* No-op wrapper handler base class. */
class JS_FRIEND_API(Wrapper) : public AbstractWrapper
/*
* 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 Wrapper(unsigned flags);
explicit IndirectWrapper(unsigned flags);
typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission;
virtual BaseProxyHandler* toBaseProxyHandler() {
return this;
}
virtual ~Wrapper();
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);
virtual ~DirectWrapper();
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;
/* ES5 Harmony derived wrapper traps. */
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
@ -136,36 +208,18 @@ class JS_FRIEND_API(Wrapper) : public AbstractWrapper
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint,
Value *vp) MOZ_OVERRIDE;
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
using AbstractWrapper::Action;
static Wrapper singleton;
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
Wrapper *handler);
using AbstractWrapper::wrappedObject;
using AbstractWrapper::wrapperHandler;
enum {
CROSS_COMPARTMENT = 1 << 0,
LAST_USED_FLAG = CROSS_COMPARTMENT
};
static DirectWrapper singleton;
static void *getWrapperFamily();
};
/* Base class for all cross compartment wrapper handlers. */
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper
{
public:
CrossCompartmentWrapper(unsigned flags);
@ -199,11 +253,10 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp);
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
static CrossCompartmentWrapper singleton;
};
@ -227,7 +280,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
};
typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<DirectWrapper> SameCompartmentSecurityWrapper;
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
/*
@ -248,6 +301,43 @@ class JS_FRIEND_API(ForceFrame)
bool enter();
};
class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
{
public:
static int sDeadObjectFamily;
explicit DeadObjectProxy();
/* 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 call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval);
virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args);
virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp);
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, unsigned indent);
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g);
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
uint32_t index, Value *vp, bool *present);
static DeadObjectProxy singleton;
};
extern JSObject *
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
unsigned flags);
@ -266,20 +356,69 @@ IsWrapper(const JSObject *obj)
// stopAtOuter is true, then this returns the outer window if it was
// previously wrapped. Otherwise, this returns the first object for
// which JSObject::isWrapper returns false.
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true,
unsigned *flagsp = NULL);
JS_FRIEND_API(JSObject *)
UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL);
// Given a JSObject, returns that object stripped of wrappers. At each stage,
// the security wrapper has the opportunity to veto the unwrap. Since checked
// code should never be unwrapping outer window wrappers, we always stop at
// outer windows.
JS_FRIEND_API(JSObject *) UnwrapObjectChecked(JSContext *cx, JSObject *obj);
JS_FRIEND_API(JSObject *)
UnwrapObjectChecked(JSContext *cx, JSObject *obj);
bool IsCrossCompartmentWrapper(const JSObject *obj);
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(const JSObject *obj);
JSObject *
NewDeadProxyObject(JSContext *cx, JSObject *parent);
void
NukeCrossCompartmentWrapper(JSObject *wrapper);
bool
RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget);
JS_FRIEND_API(bool)
RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
JSObject *newTarget);
// API to recompute all cross-compartment wrappers whose source and target
// match the given filters.
//
// These filters are designed to be ephemeral stack classes, and thus don't
// do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; }
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
}
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {}
virtual bool match(JSCompartment *c) const { return c == ours; }
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {}
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
}
};
JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter);
} /* namespace js */
#endif

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* Implementations of runtime and static assertion macros for C and C++. */
@ -44,11 +9,27 @@
#define mozilla_Assertions_h_
#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#ifdef WIN32
/*
* TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
* further depends on <windef.h>. We hardcode these few definitions manually
* because those headers clutter the global namespace with a significant
* number of undesired macros and symbols.
*/
# ifdef __cplusplus
extern "C" {
# endif
__declspec(dllimport) int __stdcall
TerminateProcess(void* hProcess, unsigned int uExitCode);
__declspec(dllimport) void* __stdcall GetCurrentProcess(void);
# ifdef __cplusplus
}
# endif
#else
# include <signal.h>
#endif
#ifdef ANDROID
@ -140,58 +121,73 @@
extern "C" {
#endif
#if defined(WIN32)
/*
* MOZ_CRASH crashes the program, plain and simple, in a Breakpad-compatible
* way, in both debug and release builds.
*
* MOZ_CRASH is a good solution for "handling" failure cases when you're
* unwilling or unable to handle them more cleanly -- for OOM, for likely memory
* corruption, and so on. It's also a good solution if you need safe behavior
* in release builds as well as debug builds. But if the failure is one that
* should be debugged and fixed, MOZ_ASSERT is generally preferable.
*/
#if defined(_MSC_VER)
/*
* We used to call DebugBreak() on Windows, but amazingly, it causes
* the MSVS 2010 debugger not to be able to recover a call stack.
*/
# define MOZ_CRASH() \
do { \
*((volatile int *) NULL) = 123; \
exit(3); \
} while (0)
#elif defined(ANDROID)
/*
* On Android, raise(SIGABRT) is handled asynchronously. Seg fault now
* so we crash immediately and capture the current call stack. We need
* to specifically use the global namespace in the C++ case.
* On MSVC use the __debugbreak compiler intrinsic, which produces an inline
* (not nested in a system function) breakpoint. This distinctively invokes
* Breakpad without requiring system library symbols on all stack-processing
* machines, as a nested breakpoint would require. We use TerminateProcess
* with the exit code aborting would generate because we don't want to invoke
* atexit handlers, destructors, library unload handlers, and so on when our
* process might be in a compromised state. We don't use abort() because
* it'd cause Windows to annoyingly pop up the process error dialog multiple
* times. See bug 345118 and bug 426163.
*
* (Technically these are Windows requirements, not MSVC requirements. But
* practically you need MSVC for debugging, and we only ship builds created
* by MSVC, so doing it this way reduces complexity.)
*/
# ifdef __cplusplus
# define MOZ_CRASH() \
do { \
*((volatile int *) NULL) = 123; \
__debugbreak(); \
*((volatile int*) NULL) = 123; \
::TerminateProcess(::GetCurrentProcess(), 3); \
} while (0)
# else
# define MOZ_CRASH() \
do { \
__debugbreak(); \
*((volatile int*) NULL) = 123; \
TerminateProcess(GetCurrentProcess(), 3); \
} while (0)
# endif
#else
# ifdef __cplusplus
# define MOZ_CRASH() \
do { \
*((volatile int*) NULL) = 123; \
::abort(); \
} while (0)
# else
# define MOZ_CRASH() \
do { \
*((volatile int *) NULL) = 123; \
*((volatile int*) NULL) = 123; \
abort(); \
} while (0)
# endif
#elif defined(__APPLE__)
/*
* On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
* trapped.
*/
# define MOZ_CRASH() \
do { \
*((volatile int *) NULL) = 123; \
raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */ \
} while (0)
#else
# define MOZ_CRASH() \
do { \
raise(SIGABRT); /* To continue from here in GDB: "signal 0". */ \
} while (0)
#endif
extern MFBT_API(void)
MOZ_Assert(const char* s, const char* file, int ln);
/*
* Prints |s| as an assertion failure (using file and ln as the location of the
* assertion) to the standard debug-output channel.
*
* Usually you should use MOZ_ASSERT instead of this method. This method is
* primarily for internal use in this header, and only secondarily for use in
* implementing release-build assertions.
*/
static MOZ_ALWAYS_INLINE void
MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
MOZ_ReportAssertionFailure(const char* s, const char* file, int ln)
{
#ifdef ANDROID
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
@ -243,7 +239,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
# define MOZ_ASSERT_HELPER1(expr) \
do { \
if (!(expr)) { \
MOZ_OutputAssertMessage(#expr, __FILE__, __LINE__); \
MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \
MOZ_CRASH(); \
} \
} while (0)
@ -251,7 +247,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
# define MOZ_ASSERT_HELPER2(expr, explain) \
do { \
if (!(expr)) { \
MOZ_OutputAssertMessage(#expr " (" explain ")", __FILE__, __LINE__); \
MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \
MOZ_CRASH(); \
} \
} while (0)
@ -302,19 +298,38 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
#endif
/* MOZ_NOT_REACHED_MARKER() expands (in compilers which support it) to an
* expression which states that it is undefined behavior for the compiler to
* reach this point. Most code should probably use the higher level
* MOZ_NOT_REACHED (which expands to this when appropriate).
/*
* MOZ_NOT_REACHED_MARKER() expands to an expression which states that it is
* undefined behavior for execution to reach this point. No guarantees are made
* about what will happen if this is reached at runtime. Most code should
* probably use the higher level MOZ_NOT_REACHED, which uses this when
* appropriate.
*/
#if defined(__clang__)
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
#elif defined(__GNUC__)
/*
* __builtin_unreachable() was implemented in gcc 4.5. If we don't have
* that, call a noreturn function; abort() will do nicely. Qualify the call
* in C++ in case there's another abort() visible in local scope.
*/
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
# else
# ifdef __cplusplus
# define MOZ_NOT_REACHED_MARKER() ::abort()
# else
# define MOZ_NOT_REACHED_MARKER() abort()
# endif
# endif
#elif defined(_MSC_VER)
# define MOZ_NOT_REACHED_MARKER() __assume(0)
# define MOZ_NOT_REACHED_MARKER() __assume(0)
#else
# ifdef __cplusplus
# define MOZ_NOT_REACHED_MARKER() ::abort()
# else
# define MOZ_NOT_REACHED_MARKER() abort()
# endif
#endif
/*
@ -334,39 +349,14 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
* MOZ_NOT_REACHED("boolean literal that's not true or false?");
* }
*/
#if defined(MOZ_NOT_REACHED_MARKER)
# if defined(DEBUG)
# define MOZ_NOT_REACHED(reason) do { \
MOZ_Assert(reason, __FILE__, __LINE__); \
MOZ_NOT_REACHED_MARKER(); \
} while (0)
# else
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
# endif
#if defined(DEBUG)
# define MOZ_NOT_REACHED(reason) \
do { \
MOZ_ASSERT(false, reason); \
MOZ_NOT_REACHED_MARKER(); \
} while (0)
#else
# if defined(__GNUC__)
/*
* On older versions of gcc we need to call a noreturn function to mark the
* code as unreachable. Since what we want is an unreachable version of
* MOZ_Assert, we use an asm label
* (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Asm-Labels.html) to create
* a new declaration to the same symbol. MOZ_ASSERT_NR should only be
* used via this macro, as it is a very specific hack to older versions of
* gcc.
*/
# define MOZ_GETASMPREFIX2(X) #X
# define MOZ_GETASMPREFIX(X) MOZ_GETASMPREFIX2(X)
# define MOZ_ASMPREFIX MOZ_GETASMPREFIX(__USER_LABEL_PREFIX__)
extern MOZ_NORETURN MFBT_API(void)
MOZ_ASSERT_NR(const char* s, const char* file, int ln) \
asm (MOZ_ASMPREFIX "MOZ_Assert");
# define MOZ_NOT_REACHED(reason) MOZ_ASSERT_NR(reason, __FILE__, __LINE__)
# elif defined(DEBUG)
# define MOZ_NOT_REACHED(reason) MOZ_Assert(reason, __FILE__, __LINE__)
# else
# define MOZ_NOT_REACHED(reason) ((void)0)
# endif
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
#endif
/*

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* Implementations of various class and method modifier attributes. */
@ -180,6 +145,19 @@
# define MOZ_NORETURN /* no support */
#endif
/*
* MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
* instrumentation shipped with Clang) to not instrument the annotated function.
* Furthermore, it will prevent the compiler from inlining the function because
* inlining currently breaks the blacklisting mechanism of AddressSanitizer.
*/
#if defined(MOZ_ASAN)
# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_address_safety_analysis))
# else
# define MOZ_ASAN_BLACKLIST
#endif
#ifdef __cplusplus
/*

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- 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/. */
@ -52,7 +52,8 @@ namespace mozilla {
*/
template<unsigned KeySize, class T>
class BloomFilter {
class BloomFilter
{
/*
* A counting Bloom filter with 8-bit counters. For now we assume
* that having two hash functions is enough, but we may revisit that
@ -101,7 +102,7 @@ class BloomFilter {
* positive rate for N == 100 and to quite bad false positive
* rates for larger N.
*/
public:
public:
BloomFilter() {
MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big");
@ -142,7 +143,7 @@ public:
void remove(uint32_t hash);
bool mightContain(uint32_t hash) const;
private:
private:
static const size_t arraySize = (1 << KeySize);
static const uint32_t keyMask = (1 << KeySize) - 1;
static const uint32_t keyShift = 16;
@ -164,67 +165,67 @@ template<unsigned KeySize, class T>
inline void
BloomFilter<KeySize, T>::clear()
{
memset(counters, 0, arraySize);
memset(counters, 0, arraySize);
}
template<unsigned KeySize, class T>
inline void
BloomFilter<KeySize, T>::add(uint32_t hash)
{
uint8_t& slot1 = firstSlot(hash);
if (MOZ_LIKELY(!full(slot1)))
++slot1;
uint8_t& slot1 = firstSlot(hash);
if (MOZ_LIKELY(!full(slot1)))
++slot1;
uint8_t& slot2 = secondSlot(hash);
if (MOZ_LIKELY(!full(slot2)))
++slot2;
uint8_t& slot2 = secondSlot(hash);
if (MOZ_LIKELY(!full(slot2)))
++slot2;
}
template<unsigned KeySize, class T>
MOZ_ALWAYS_INLINE void
BloomFilter<KeySize, T>::add(const T* t)
{
uint32_t hash = t->hash();
return add(hash);
uint32_t hash = t->hash();
return add(hash);
}
template<unsigned KeySize, class T>
inline void
BloomFilter<KeySize, T>::remove(uint32_t hash)
{
// If the slots are full, we don't know whether we bumped them to be
// there when we added or not, so just leave them full.
uint8_t& slot1 = firstSlot(hash);
if (MOZ_LIKELY(!full(slot1)))
--slot1;
// If the slots are full, we don't know whether we bumped them to be
// there when we added or not, so just leave them full.
uint8_t& slot1 = firstSlot(hash);
if (MOZ_LIKELY(!full(slot1)))
--slot1;
uint8_t& slot2 = secondSlot(hash);
if (MOZ_LIKELY(!full(slot2)))
--slot2;
uint8_t& slot2 = secondSlot(hash);
if (MOZ_LIKELY(!full(slot2)))
--slot2;
}
template<unsigned KeySize, class T>
MOZ_ALWAYS_INLINE void
BloomFilter<KeySize, T>::remove(const T* t)
{
uint32_t hash = t->hash();
remove(hash);
uint32_t hash = t->hash();
remove(hash);
}
template<unsigned KeySize, class T>
MOZ_ALWAYS_INLINE bool
BloomFilter<KeySize, T>::mightContain(uint32_t hash) const
{
// Check that all the slots for this hash contain something
return firstSlot(hash) && secondSlot(hash);
// Check that all the slots for this hash contain something
return firstSlot(hash) && secondSlot(hash);
}
template<unsigned KeySize, class T>
MOZ_ALWAYS_INLINE bool
BloomFilter<KeySize, T>::mightContain(const T* t) const
{
uint32_t hash = t->hash();
return mightContain(hash);
uint32_t hash = t->hash();
return mightContain(hash);
}
} // namespace mozilla

View File

@ -0,0 +1,809 @@
/* -*- 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/. */
/* Provides checked integers, detecting integer overflow and divide-by-0. */
#ifndef mozilla_CheckedInt_h_
#define mozilla_CheckedInt_h_
/*
* Build options. Comment out these #defines to disable the corresponding
* optional feature. Disabling features may be useful for code using
* CheckedInt outside of Mozilla (e.g. WebKit)
*/
// Enable usage of MOZ_STATIC_ASSERT to check for unsupported types.
// If disabled, static asserts are replaced by regular assert().
#define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
/*
* End of build options
*/
#ifdef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS
# include "mozilla/Assertions.h"
#else
# ifndef MOZ_STATIC_ASSERT
# include <cassert>
# define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason)
# define MOZ_ASSERT(cond, reason) assert((cond) && reason)
# endif
#endif
#include "mozilla/StandardInteger.h"
#include <climits>
#include <cstddef>
namespace mozilla {
namespace detail {
/*
* Step 1: manually record supported types
*
* What's nontrivial here is that there are different families of integer
* types: basic integer types and stdint types. It is merrily undefined which
* types from one family may be just typedefs for a type from another family.
*
* For example, on GCC 4.6, aside from the basic integer types, the only other
* type that isn't just a typedef for some of them, is int8_t.
*/
struct UnsupportedType {};
template<typename IntegerType>
struct IsSupportedPass2
{
static const bool value = false;
};
template<typename IntegerType>
struct IsSupported
{
static const bool value = IsSupportedPass2<IntegerType>::value;
};
template<>
struct IsSupported<int8_t>
{ static const bool value = true; };
template<>
struct IsSupported<uint8_t>
{ static const bool value = true; };
template<>
struct IsSupported<int16_t>
{ static const bool value = true; };
template<>
struct IsSupported<uint16_t>
{ static const bool value = true; };
template<>
struct IsSupported<int32_t>
{ static const bool value = true; };
template<>
struct IsSupported<uint32_t>
{ static const bool value = true; };
template<>
struct IsSupported<int64_t>
{ static const bool value = true; };
template<>
struct IsSupported<uint64_t>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<char>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<unsigned char>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<short>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<unsigned short>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<int>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<unsigned int>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<long>
{ static const bool value = true; };
template<>
struct IsSupportedPass2<unsigned long>
{ static const bool value = true; };
/*
* Step 2: some integer-traits kind of stuff.
*/
template<size_t Size, bool Signedness>
struct StdintTypeForSizeAndSignedness
{};
template<>
struct StdintTypeForSizeAndSignedness<1, true>
{ typedef int8_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<1, false>
{ typedef uint8_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<2, true>
{ typedef int16_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<2, false>
{ typedef uint16_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<4, true>
{ typedef int32_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<4, false>
{ typedef uint32_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<8, true>
{ typedef int64_t Type; };
template<>
struct StdintTypeForSizeAndSignedness<8, false>
{ typedef uint64_t Type; };
template<typename IntegerType>
struct UnsignedType
{
typedef typename StdintTypeForSizeAndSignedness<sizeof(IntegerType),
false>::Type Type;
};
template<typename IntegerType>
struct IsSigned
{
static const bool value = IntegerType(-1) <= IntegerType(0);
};
template<typename IntegerType, size_t Size = sizeof(IntegerType)>
struct TwiceBiggerType
{
typedef typename StdintTypeForSizeAndSignedness<
sizeof(IntegerType) * 2,
IsSigned<IntegerType>::value
>::Type Type;
};
template<typename IntegerType>
struct TwiceBiggerType<IntegerType, 8>
{
typedef UnsupportedType Type;
};
template<typename IntegerType>
struct PositionOfSignBit
{
static const size_t value = CHAR_BIT * sizeof(IntegerType) - 1;
};
template<typename IntegerType>
struct MinValue
{
private:
typedef typename UnsignedType<IntegerType>::Type UnsignedIntegerType;
static const size_t PosOfSignBit = PositionOfSignBit<IntegerType>::value;
public:
// Bitwise ops may return a larger type, that's why we cast explicitly.
// In C++, left bit shifts on signed values is undefined by the standard
// unless the shifted value is representable.
// Notice that signed-to-unsigned conversions are always well-defined in
// the standard as the value congruent to 2**n, as expected. By contrast,
// unsigned-to-signed is only well-defined if the value is representable.
static const IntegerType value =
IsSigned<IntegerType>::value
? IntegerType(UnsignedIntegerType(1) << PosOfSignBit)
: IntegerType(0);
};
template<typename IntegerType>
struct MaxValue
{
// Tricksy, but covered by the unit test.
// Relies heavily on the type of MinValue<IntegerType>::value
// being IntegerType.
static const IntegerType value = ~MinValue<IntegerType>::value;
};
/*
* Step 3: Implement the actual validity checks.
*
* Ideas taken from IntegerLib, code different.
*/
template<typename T>
inline bool
HasSignBit(T x)
{
// In C++, right bit shifts on negative values is undefined by the standard.
// Notice that signed-to-unsigned conversions are always well-defined in the
// standard, as the value congruent modulo 2**n as expected. By contrast,
// unsigned-to-signed is only well-defined if the value is representable.
return bool(typename UnsignedType<T>::Type(x)
>> PositionOfSignBit<T>::value);
}
// Bitwise ops may return a larger type, so it's good to use this inline
// helper guaranteeing that the result is really of type T.
template<typename T>
inline T
BinaryComplement(T x)
{
return ~x;
}
template<typename T,
typename U,
bool IsTSigned = IsSigned<T>::value,
bool IsUSigned = IsSigned<U>::value>
struct DoesRangeContainRange
{
};
template<typename T, typename U, bool Signedness>
struct DoesRangeContainRange<T, U, Signedness, Signedness>
{
static const bool value = sizeof(T) >= sizeof(U);
};
template<typename T, typename U>
struct DoesRangeContainRange<T, U, true, false>
{
static const bool value = sizeof(T) > sizeof(U);
};
template<typename T, typename U>
struct DoesRangeContainRange<T, U, false, true>
{
static const bool value = false;
};
template<typename T,
typename U,
bool IsTSigned = IsSigned<T>::value,
bool IsUSigned = IsSigned<U>::value,
bool DoesTRangeContainURange = DoesRangeContainRange<T, U>::value>
struct IsInRangeImpl {};
template<typename T, typename U, bool IsTSigned, bool IsUSigned>
struct IsInRangeImpl<T, U, IsTSigned, IsUSigned, true>
{
static bool run(U)
{
return true;
}
};
template<typename T, typename U>
struct IsInRangeImpl<T, U, true, true, false>
{
static bool run(U x)
{
return x <= MaxValue<T>::value && x >= MinValue<T>::value;
}
};
template<typename T, typename U>
struct IsInRangeImpl<T, U, false, false, false>
{
static bool run(U x)
{
return x <= MaxValue<T>::value;
}
};
template<typename T, typename U>
struct IsInRangeImpl<T, U, true, false, false>
{
static bool run(U x)
{
return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value);
}
};
template<typename T, typename U>
struct IsInRangeImpl<T, U, false, true, false>
{
static bool run(U x)
{
return sizeof(T) >= sizeof(U)
? x >= 0
: x >= 0 && x <= U(MaxValue<T>::value);
}
};
template<typename T, typename U>
inline bool
IsInRange(U x)
{
return IsInRangeImpl<T, U>::run(x);
}
template<typename T>
inline bool
IsAddValid(T x, T y)
{
// Addition is valid if the sign of x+y is equal to either that of x or that
// of y. Since the value of x+y is undefined if we have a signed type, we
// compute it using the unsigned type of the same size.
// Beware! These bitwise operations can return a larger integer type,
// if T was a small type like int8_t, so we explicitly cast to T.
typename UnsignedType<T>::Type ux = x;
typename UnsignedType<T>::Type uy = y;
typename UnsignedType<T>::Type result = ux + uy;
return IsSigned<T>::value
? HasSignBit(BinaryComplement(T((result ^ x) & (result ^ y))))
: BinaryComplement(x) >= y;
}
template<typename T>
inline bool
IsSubValid(T x, T y)
{
// Subtraction is valid if either x and y have same sign, or x-y and x have
// same sign. Since the value of x-y is undefined if we have a signed type,
// we compute it using the unsigned type of the same size.
typename UnsignedType<T>::Type ux = x;
typename UnsignedType<T>::Type uy = y;
typename UnsignedType<T>::Type result = ux - uy;
return IsSigned<T>::value
? HasSignBit(BinaryComplement(T((result ^ x) & (x ^ y))))
: x >= y;
}
template<typename T,
bool IsSigned = IsSigned<T>::value,
bool TwiceBiggerTypeIsSupported =
IsSupported<typename TwiceBiggerType<T>::Type>::value>
struct IsMulValidImpl {};
template<typename T, bool IsSigned>
struct IsMulValidImpl<T, IsSigned, true>
{
static bool run(T x, T y)
{
typedef typename TwiceBiggerType<T>::Type TwiceBiggerType;
TwiceBiggerType product = TwiceBiggerType(x) * TwiceBiggerType(y);
return IsInRange<T>(product);
}
};
template<typename T>
struct IsMulValidImpl<T, true, false>
{
static bool run(T x, T y)
{
const T max = MaxValue<T>::value;
const T min = MinValue<T>::value;
if (x == 0 || y == 0)
return true;
if (x > 0) {
return y > 0
? x <= max / y
: y >= min / x;
}
// If we reach this point, we know that x < 0.
return y > 0
? x >= min / y
: y >= max / x;
}
};
template<typename T>
struct IsMulValidImpl<T, false, false>
{
static bool run(T x, T y)
{
return y == 0 || x <= MaxValue<T>::value / y;
}
};
template<typename T>
inline bool
IsMulValid(T x, T y)
{
return IsMulValidImpl<T>::run(x, y);
}
template<typename T>
inline bool
IsDivValid(T x, T y)
{
// Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max.
return y != 0 &&
!(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
}
// This is just to shut up msvc warnings about negating unsigned ints.
template<typename T, bool IsSigned = IsSigned<T>::value>
struct OppositeIfSignedImpl
{
static T run(T x) { return -x; }
};
template<typename T>
struct OppositeIfSignedImpl<T, false>
{
static T run(T x) { return x; }
};
template<typename T>
inline T
OppositeIfSigned(T x)
{
return OppositeIfSignedImpl<T>::run(x);
}
} // namespace detail
/*
* Step 4: Now define the CheckedInt class.
*/
/**
* @class CheckedInt
* @brief Integer wrapper class checking for integer overflow and other errors
* @param T the integer type to wrap. Can be any type among the following:
* - any basic integer type such as |int|
* - any stdint type such as |int8_t|
*
* This class implements guarded integer arithmetic. Do a computation, check
* that isValid() returns true, you then have a guarantee that no problem, such
* as integer overflow, happened during this computation, and you can call
* value() to get the plain integer value.
*
* The arithmetic operators in this class are guaranteed not to raise a signal
* (e.g. in case of a division by zero).
*
* For example, suppose that you want to implement a function that computes
* (x+y)/z, that doesn't crash if z==0, and that reports on error (divide by
* zero or integer overflow). You could code it as follows:
@code
bool computeXPlusYOverZ(int x, int y, int z, int *result)
{
CheckedInt<int> checkedResult = (CheckedInt<int>(x) + y) / z;
if (checkedResult.isValid()) {
*result = checkedResult.value();
return true;
} else {
return false;
}
}
@endcode
*
* Implicit conversion from plain integers to checked integers is allowed. The
* plain integer is checked to be in range before being casted to the
* destination type. This means that the following lines all compile, and the
* resulting CheckedInts are correctly detected as valid or invalid:
* @code
// 1 is of type int, is found to be in range for uint8_t, x is valid
CheckedInt<uint8_t> x(1);
// -1 is of type int, is found not to be in range for uint8_t, x is invalid
CheckedInt<uint8_t> x(-1);
// -1 is of type int, is found to be in range for int8_t, x is valid
CheckedInt<int8_t> x(-1);
// 1000 is of type int16_t, is found not to be in range for int8_t,
// x is invalid
CheckedInt<int8_t> x(int16_t(1000));
// 3123456789 is of type uint32_t, is found not to be in range for int32_t,
// x is invalid
CheckedInt<int32_t> x(uint32_t(3123456789));
* @endcode
* Implicit conversion from
* checked integers to plain integers is not allowed. As shown in the
* above example, to get the value of a checked integer as a normal integer,
* call value().
*
* Arithmetic operations between checked and plain integers is allowed; the
* result type is the type of the checked integer.
*
* Checked integers of different types cannot be used in the same arithmetic
* expression.
*
* There are convenience typedefs for all stdint types, of the following form
* (these are just 2 examples):
@code
typedef CheckedInt<int32_t> CheckedInt32;
typedef CheckedInt<uint16_t> CheckedUint16;
@endcode
*/
template<typename T>
class CheckedInt
{
protected:
T mValue;
bool mIsValid;
template<typename U>
CheckedInt(U value, bool isValid) : mValue(value), mIsValid(isValid)
{
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
"This type is not supported by CheckedInt");
}
public:
/**
* Constructs a checked integer with given @a value. The checked integer is
* initialized as valid or invalid depending on whether the @a value
* is in range.
*
* This constructor is not explicit. Instead, the type of its argument is a
* separate template parameter, ensuring that no conversion is performed
* before this constructor is actually called. As explained in the above
* documentation for class CheckedInt, this constructor checks that its
* argument is valid.
*/
template<typename U>
CheckedInt(U value)
: mValue(T(value)),
mIsValid(detail::IsInRange<T>(value))
{
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
"This type is not supported by CheckedInt");
}
/** Constructs a valid checked integer with initial value 0 */
CheckedInt() : mValue(0), mIsValid(true)
{
MOZ_STATIC_ASSERT(detail::IsSupported<T>::value,
"This type is not supported by CheckedInt");
}
/** @returns the actual value */
T value() const
{
MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)");
return mValue;
}
/**
* @returns true if the checked integer is valid, i.e. is not the result
* of an invalid operation or of an operation involving an invalid checked
* integer
*/
bool isValid() const
{
return mIsValid;
}
template<typename U>
friend CheckedInt<U> operator +(const CheckedInt<U>& lhs,
const CheckedInt<U>& rhs);
template<typename U>
CheckedInt& operator +=(U rhs);
template<typename U>
friend CheckedInt<U> operator -(const CheckedInt<U>& lhs,
const CheckedInt<U> &rhs);
template<typename U>
CheckedInt& operator -=(U rhs);
template<typename U>
friend CheckedInt<U> operator *(const CheckedInt<U>& lhs,
const CheckedInt<U> &rhs);
template<typename U>
CheckedInt& operator *=(U rhs);
template<typename U>
friend CheckedInt<U> operator /(const CheckedInt<U>& lhs,
const CheckedInt<U> &rhs);
template<typename U>
CheckedInt& operator /=(U rhs);
CheckedInt operator -() const
{
// Circumvent msvc warning about - applied to unsigned int.
// if we're unsigned, the only valid case anyway is 0
// in which case - is a no-op.
T result = detail::OppositeIfSigned(mValue);
/* Help the compiler perform RVO (return value optimization). */
return CheckedInt(result,
mIsValid && detail::IsSubValid(T(0),
mValue));
}
/**
* @returns true if the left and right hand sides are valid
* and have the same value.
*
* Note that these semantics are the reason why we don't offer
* a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b)
* but that would mean that whenever a or b is invalid, a!=b
* is always true, which would be very confusing.
*
* For similar reasons, operators <, >, <=, >= would be very tricky to
* specify, so we just avoid offering them.
*
* Notice that these == semantics are made more reasonable by these facts:
* 1. a==b implies equality at the raw data level
* (the converse is false, as a==b is never true among invalids)
* 2. This is similar to the behavior of IEEE floats, where a==b
* means that a and b have the same value *and* neither is NaN.
*/
bool operator ==(const CheckedInt& other) const
{
return mIsValid && other.mIsValid && mValue == other.mValue;
}
/** prefix ++ */
CheckedInt& operator++()
{
*this += 1;
return *this;
}
/** postfix ++ */
CheckedInt operator++(int)
{
CheckedInt tmp = *this;
*this += 1;
return tmp;
}
/** prefix -- */
CheckedInt& operator--()
{
*this -= 1;
return *this;
}
/** postfix -- */
CheckedInt operator--(int)
{
CheckedInt tmp = *this;
*this -= 1;
return tmp;
}
private:
/**
* The !=, <, <=, >, >= operators are disabled:
* see the comment on operator==.
*/
template<typename U>
bool operator !=(U other) const MOZ_DELETE;
template<typename U>
bool operator <(U other) const MOZ_DELETE;
template<typename U>
bool operator <=(U other) const MOZ_DELETE;
template<typename U>
bool operator >(U other) const MOZ_DELETE;
template<typename U>
bool operator >=(U other) const MOZ_DELETE;
};
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \
template<typename T> \
inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, \
const CheckedInt<T> &rhs) \
{ \
if (!detail::Is##NAME##Valid(lhs.mValue, rhs.mValue)) \
return CheckedInt<T>(0, false); \
\
return CheckedInt<T>(lhs.mValue OP rhs.mValue, \
lhs.mIsValid && rhs.mIsValid); \
}
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
// Implement castToCheckedInt<T>(x), making sure that
// - it allows x to be either a CheckedInt<T> or any integer type
// that can be casted to T
// - if x is already a CheckedInt<T>, we just return a reference to it,
// instead of copying it (optimization)
namespace detail {
template<typename T, typename U>
struct CastToCheckedIntImpl
{
typedef CheckedInt<T> ReturnType;
static CheckedInt<T> run(U u) { return u; }
};
template<typename T>
struct CastToCheckedIntImpl<T, CheckedInt<T> >
{
typedef const CheckedInt<T>& ReturnType;
static const CheckedInt<T>& run(const CheckedInt<T>& u) { return u; }
};
} // namespace detail
template<typename T, typename U>
inline typename detail::CastToCheckedIntImpl<T, U>::ReturnType
castToCheckedInt(U u)
{
return detail::CastToCheckedIntImpl<T, U>::run(u);
}
#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \
template<typename T> \
template<typename U> \
CheckedInt<T>& CheckedInt<T>::operator COMPOUND_OP(U rhs) \
{ \
*this = *this OP castToCheckedInt<T>(rhs); \
return *this; \
} \
template<typename T, typename U> \
inline CheckedInt<T> operator OP(const CheckedInt<T> &lhs, U rhs) \
{ \
return lhs OP castToCheckedInt<T>(rhs); \
} \
template<typename T, typename U> \
inline CheckedInt<T> operator OP(U lhs, const CheckedInt<T> &rhs) \
{ \
return castToCheckedInt<T>(lhs) OP rhs; \
}
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=)
MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=)
#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS
template<typename T, typename U>
inline bool
operator ==(const CheckedInt<T> &lhs, U rhs)
{
return lhs == castToCheckedInt<T>(rhs);
}
template<typename T, typename U>
inline bool
operator ==(U lhs, const CheckedInt<T> &rhs)
{
return castToCheckedInt<T>(lhs) == rhs;
}
// Convenience typedefs.
typedef CheckedInt<int8_t> CheckedInt8;
typedef CheckedInt<uint8_t> CheckedUint8;
typedef CheckedInt<int16_t> CheckedInt16;
typedef CheckedInt<uint16_t> CheckedUint16;
typedef CheckedInt<int32_t> CheckedInt32;
typedef CheckedInt<uint32_t> CheckedUint32;
typedef CheckedInt<int64_t> CheckedInt64;
typedef CheckedInt<uint64_t> CheckedUint64;
} // namespace mozilla
#endif /* mozilla_CheckedInt_h_ */

View File

@ -226,16 +226,6 @@ MOZ_DOUBLE_MIN_VALUE()
return pun.d;
}
/** Computes a 32-bit hash of the given double. */
static MOZ_ALWAYS_INLINE uint32_t
MOZ_HASH_DOUBLE(double d)
{
union MozDoublePun pun;
pun.d = d;
return ((uint32_t)(pun.u >> 32)) ^ ((uint32_t)(pun.u));
}
static MOZ_ALWAYS_INLINE int
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
{

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sw=4 et tw=99 ft=cpp: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
* Ms2ger <ms2ger@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
@ -52,6 +17,7 @@
namespace mozilla {
namespace detail {
/*
* The following classes are designed to cause assertions to detect
* inadvertent use of guard objects as temporaries. In other words,
@ -59,11 +25,11 @@ namespace detail {
* destructor (and is never otherwise referenced), the intended use
* might be:
*
* AutoRestore savePainting(mIsPainting);
* AutoRestore savePainting(mIsPainting);
*
* but is is easy to accidentally write:
*
* AutoRestore(mIsPainting);
* AutoRestore(mIsPainting);
*
* which compiles just fine, but runs the destructor well before the
* intended time.
@ -106,14 +72,14 @@ class MOZ_EXPORT_API(GuardObjectNotifier)
bool* statementDone;
public:
GuardObjectNotifier() : statementDone(NULL) {}
GuardObjectNotifier() : statementDone(NULL) { }
~GuardObjectNotifier() {
*statementDone = true;
*statementDone = true;
}
void setStatementDone(bool* statementIsDone) {
statementDone = statementIsDone;
statementDone = statementIsDone;
}
};
@ -123,25 +89,24 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
bool statementDone;
public:
GuardObjectNotificationReceiver() : statementDone(false) {}
GuardObjectNotificationReceiver() : statementDone(false) { }
~GuardObjectNotificationReceiver() {
/*
* Assert that the guard object was not used as a temporary.
* (Note that this assert might also fire if init is not called
* because the guard object's implementation is not using the
* above macros correctly.)
*/
MOZ_ASSERT(statementDone);
/*
* Assert that the guard object was not used as a temporary. (Note that
* this assert might also fire if init is not called because the guard
* object's implementation is not using the above macros correctly.)
*/
MOZ_ASSERT(statementDone);
}
void init(const GuardObjectNotifier& constNotifier) {
/*
* constNotifier is passed as a const reference so that we can pass a
* temporary, but we really intend it as non-const.
*/
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
notifier.setStatementDone(&statementDone);
/*
* constNotifier is passed as a const reference so that we can pass a
* temporary, but we really intend it as non-const.
*/
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
notifier.setStatementDone(&statementDone);
}
};

View File

@ -1,11 +1,9 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* This Source Code Form is subject to the terms of the Mozilla Public
/* -*- 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/. */
/* Utilities for hashing */
/* Utilities for hashing. */
/*
* This file exports functions for hashing data down to a 32-bit value,
@ -26,16 +24,18 @@
*
* You can chain these functions together to hash complex objects. For example:
*
* class ComplexObject {
* char* str;
* uint32_t uint1, uint2;
* void (*callbackFn)();
* class ComplexObject
* {
* char* str;
* uint32_t uint1, uint2;
* void (*callbackFn)();
*
* uint32_t Hash() {
* uint32_t hash = HashString(str);
* hash = AddToHash(hash, uint1, uint2);
* return AddToHash(hash, callbackFn);
* }
* public:
* uint32_t hash() {
* uint32_t hash = HashString(str);
* hash = AddToHash(hash, uint1, uint2);
* return AddToHash(hash, callbackFn);
* }
* };
*
* If you want to hash an nsAString or nsACString, use the HashString functions
@ -48,6 +48,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/StandardInteger.h"
#include "mozilla/Types.h"
#ifdef __cplusplus
namespace mozilla {

View File

@ -1,3 +1,4 @@
/* -*- 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/. */
@ -7,8 +8,8 @@
* boolean predicate should be branch-predicted.
*/
#ifndef Likely_h_
#define Likely_h_
#ifndef mozilla_Likely_h_
#define mozilla_Likely_h_
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
# define MOZ_LIKELY(x) (__builtin_expect((x), 1))
@ -18,4 +19,4 @@
# define MOZ_UNLIKELY(x) (x)
#endif
#endif /* Likely_h_ */
#endif /* mozilla_Likely_h_ */

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 tw=80 et cin:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2012
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Justin Lebar <justin.lebar@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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 type-safe doubly-linked list class. */
@ -53,36 +18,30 @@
*
* class Observer : public LinkedListElement<Observer>
* {
* void observe(char* topic) { ... }
* public:
* void observe(char* topic) { ... }
* };
*
* class ObserverContainer
* {
* private:
* LinkedList<ElemType> list;
* private:
* LinkedList<Observer> list;
*
* public:
*
* void addObserver(Observer* observer)
* {
* // Will assert if |observer| is part of another list.
* list.insertBack(observer);
* }
*
* void removeObserver(Observer* observer)
* {
* // Will assert if |observer| is not part of some list.
* observer.remove();
* }
*
* void notifyObservers(char* topic)
* {
* for (Observer* o = list.getFirst();
* o != NULL;
* o = o->getNext()) {
* o->Observe(topic);
* public:
* void addObserver(Observer* observer) {
* // Will assert if |observer| is part of another list.
* list.insertBack(observer);
* }
*
* void removeObserver(Observer* observer) {
* // Will assert if |observer| is not part of some list.
* observer.remove();
* }
*
* void notifyObservers(char* topic) {
* for (Observer* o = list.getFirst(); o != NULL; o = o->getNext())
* o->Observe(topic);
* }
* }
* };
*
*/
@ -137,43 +96,41 @@ class LinkedListElement
* lists, and supporting this painlessly was a key design criterion.
*/
private:
private:
LinkedListElement* next;
LinkedListElement* prev;
const bool isSentinel;
public:
LinkedListElement()
: next(this)
, prev(this)
, isSentinel(false)
{
}
public:
LinkedListElement() : next(this), prev(this), isSentinel(false) { }
/*
* Get the next element in the list, or NULL if this is the last element in
* the list.
*/
T* getNext()
{
return next->asT();
T* getNext() {
return next->asT();
}
const T* getNext() const {
return next->asT();
}
/*
* Get the previous element in the list, or NULL if this is the first element
* in the list.
*/
T* getPrevious()
{
return prev->asT();
T* getPrevious() {
return prev->asT();
}
const T* getPrevious() const {
return prev->asT();
}
/*
* Insert elem after this element in the list. |this| must be part of a
* linked list when you call setNext(); otherwise, this method will assert.
*/
void setNext(T* elem)
{
void setNext(T* elem) {
MOZ_ASSERT(isInList());
setNextUnsafe(elem);
}
@ -183,50 +140,44 @@ public:
* linked list when you call setPrevious(); otherwise, this method will
* assert.
*/
void setPrevious(T* elem)
{
MOZ_ASSERT(isInList());
setPreviousUnsafe(elem);
void setPrevious(T* elem) {
MOZ_ASSERT(isInList());
setPreviousUnsafe(elem);
}
/*
* Remove this element from the list which contains it. If this element is
* not currently part of a linked list, this method asserts.
*/
void remove()
{
MOZ_ASSERT(isInList());
void remove() {
MOZ_ASSERT(isInList());
prev->next = next;
next->prev = prev;
next = this;
prev = this;
prev->next = next;
next->prev = prev;
next = this;
prev = this;
}
/*
* Return true if |this| part is of a linked list, and false otherwise.
*/
bool isInList()
{
MOZ_ASSERT((next == this) == (prev == this));
return next != this;
bool isInList() const {
MOZ_ASSERT((next == this) == (prev == this));
return next != this;
}
private:
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
private:
friend class LinkedList<T>;
enum NodeKind {
NODE_KIND_NORMAL,
NODE_KIND_SENTINEL
NODE_KIND_NORMAL,
NODE_KIND_SENTINEL
};
LinkedListElement(NodeKind nodeKind)
: next(this)
, prev(this)
, isSentinel(nodeKind == NODE_KIND_SENTINEL)
: next(this),
prev(this),
isSentinel(nodeKind == NODE_KIND_SENTINEL)
{
}
@ -234,125 +185,123 @@ private:
* Return |this| cast to T* if we're a normal node, or return NULL if we're
* a sentinel node.
*/
T* asT()
{
if (isSentinel)
return NULL;
T* asT() {
if (isSentinel)
return NULL;
return static_cast<T*>(this);
return static_cast<T*>(this);
}
const T* asT() const {
if (isSentinel)
return NULL;
return static_cast<const T*>(this);
}
/*
* Insert elem after this element, but don't check that this element is in
* the list. This is called by LinkedList::insertFront().
*/
void setNextUnsafe(T* elem)
{
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
MOZ_ASSERT(!listElem->isInList());
void setNextUnsafe(T* elem) {
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
MOZ_ASSERT(!listElem->isInList());
listElem->next = this->next;
listElem->prev = this;
this->next->prev = listElem;
this->next = listElem;
listElem->next = this->next;
listElem->prev = this;
this->next->prev = listElem;
this->next = listElem;
}
/*
* Insert elem before this element, but don't check that this element is in
* the list. This is called by LinkedList::insertBack().
*/
void setPreviousUnsafe(T* elem)
{
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
MOZ_ASSERT(!listElem->isInList());
void setPreviousUnsafe(T* elem) {
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
MOZ_ASSERT(!listElem->isInList());
listElem->next = this;
listElem->prev = this->prev;
this->prev->next = listElem;
this->prev = listElem;
listElem->next = this;
listElem->prev = this->prev;
this->prev->next = listElem;
this->prev = listElem;
}
private:
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
};
template<typename T>
class LinkedList
{
private:
private:
LinkedListElement<T> sentinel;
public:
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
LinkedList()
: sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL)
{
}
public:
LinkedList() : sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL) { }
/*
* Add elem to the front of the list.
*/
void insertFront(T* elem)
{
/* Bypass setNext()'s this->isInList() assertion. */
sentinel.setNextUnsafe(elem);
void insertFront(T* elem) {
/* Bypass setNext()'s this->isInList() assertion. */
sentinel.setNextUnsafe(elem);
}
/*
* Add elem to the back of the list.
*/
void insertBack(T* elem)
{
sentinel.setPreviousUnsafe(elem);
void insertBack(T* elem) {
sentinel.setPreviousUnsafe(elem);
}
/*
* Get the first element of the list, or NULL if the list is empty.
*/
T* getFirst()
{
return sentinel.getNext();
T* getFirst() {
return sentinel.getNext();
}
const T* getFirst() const {
return sentinel.getNext();
}
/*
* Get the last element of the list, or NULL if the list is empty.
*/
T* getLast()
{
return sentinel.getPrevious();
T* getLast() {
return sentinel.getPrevious();
}
const T* getLast() const {
return sentinel.getPrevious();
}
/*
* Get and remove the first element of the list. If the list is empty,
* return NULL.
*/
T* popFirst()
{
T* ret = sentinel.getNext();
if (ret)
static_cast<LinkedListElement<T>*>(ret)->remove();
return ret;
T* popFirst() {
T* ret = sentinel.getNext();
if (ret)
static_cast<LinkedListElement<T>*>(ret)->remove();
return ret;
}
/*
* Get and remove the last element of the list. If the list is empty,
* return NULL.
*/
T* popLast()
{
T* ret = sentinel.getPrevious();
if (ret)
static_cast<LinkedListElement<T>*>(ret)->remove();
return ret;
T* popLast() {
T* ret = sentinel.getPrevious();
if (ret)
static_cast<LinkedListElement<T>*>(ret)->remove();
return ret;
}
/*
* Return true if the list is empty, or false otherwise.
*/
bool isEmpty()
{
return !sentinel.isInList();
bool isEmpty() const {
return !sentinel.isInList();
}
/*
@ -361,71 +310,73 @@ public:
* This runs in time linear to the list's length, because we have to mark
* each element as not in the list.
*/
void clear()
{
while (popFirst())
continue;
void clear() {
while (popFirst())
continue;
}
/*
* In a debug build, make sure that the list is sane (no cycles, consistent
* next/prev pointers, only one sentinel). Has no effect in release builds.
*/
void debugAssertIsSane()
{
void debugAssertIsSane() const {
#ifdef DEBUG
/*
* Check for cycles in the forward singly-linked list using the
* tortoise/hare algorithm.
*/
for (LinkedListElement<T>* slow = sentinel.next,
* fast1 = sentinel.next->next,
* fast2 = sentinel.next->next->next;
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
slow = slow->next,
fast1 = fast2->next,
fast2 = fast1->next) {
const LinkedListElement<T>* slow;
const LinkedListElement<T>* fast1;
const LinkedListElement<T>* fast2;
MOZ_ASSERT(slow != fast1);
MOZ_ASSERT(slow != fast2);
}
/*
* Check for cycles in the forward singly-linked list using the
* tortoise/hare algorithm.
*/
for (slow = sentinel.next,
fast1 = sentinel.next->next,
fast2 = sentinel.next->next->next;
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
slow = slow->next, fast1 = fast2->next, fast2 = fast1->next)
{
MOZ_ASSERT(slow != fast1);
MOZ_ASSERT(slow != fast2);
}
/* Check for cycles in the backward singly-linked list. */
for (LinkedListElement<T>* slow = sentinel.prev,
* fast1 = sentinel.prev->prev,
* fast2 = sentinel.prev->prev->prev;
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
slow = slow->prev,
fast1 = fast2->prev,
fast2 = fast1->prev) {
/* Check for cycles in the backward singly-linked list. */
for (slow = sentinel.prev,
fast1 = sentinel.prev->prev,
fast2 = sentinel.prev->prev->prev;
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
slow = slow->prev, fast1 = fast2->prev, fast2 = fast1->prev)
{
MOZ_ASSERT(slow != fast1);
MOZ_ASSERT(slow != fast2);
}
MOZ_ASSERT(slow != fast1);
MOZ_ASSERT(slow != fast2);
}
/*
* Check that |sentinel| is the only node in the list with
* isSentinel == true.
*/
for (const LinkedListElement<T>* elem = sentinel.next;
elem != sentinel;
elem = elem->next)
{
MOZ_ASSERT(!elem->isSentinel);
}
/*
* Check that |sentinel| is the only node in the list with
* isSentinel == true.
*/
for (LinkedListElement<T>* elem = sentinel.next;
elem != sentinel;
elem = elem->next) {
/* Check that the next/prev pointers match up. */
const LinkedListElement<T>* prev = sentinel;
const LinkedListElement<T>* cur = sentinel.next;
do {
MOZ_ASSERT(cur->prev == prev);
MOZ_ASSERT(prev->next == cur);
MOZ_ASSERT(!elem->isSentinel);
}
/* Check that the next/prev pointers match up. */
LinkedListElement<T>* prev = sentinel;
LinkedListElement<T>* cur = sentinel.next;
do {
MOZ_ASSERT(cur->prev == prev);
MOZ_ASSERT(prev->next == cur);
prev = cur;
cur = cur->next;
} while (cur != sentinel);
prev = cur;
cur = cur->next;
} while (cur != sentinel);
#endif /* ifdef DEBUG */
}
private:
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
};
} /* namespace mozilla */

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/*
* Implements a smart pointer asserted to remain within a range specified at
@ -71,7 +36,7 @@ namespace mozilla {
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
* implement bounds checking in debug builds.
*/
template <typename T>
template<typename T>
class RangedPtr
{
T* ptr;
@ -82,16 +47,16 @@ class RangedPtr
#endif
void checkSanity() {
MOZ_ASSERT(rangeStart <= ptr);
MOZ_ASSERT(ptr <= rangeEnd);
MOZ_ASSERT(rangeStart <= ptr);
MOZ_ASSERT(ptr <= rangeEnd);
}
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
RangedPtr<T> create(T *ptr) const {
#ifdef DEBUG
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
#else
return RangedPtr<T>(ptr, NULL, size_t(0));
return RangedPtr<T>(ptr, NULL, size_t(0));
#endif
}
@ -102,8 +67,8 @@ class RangedPtr
, rangeStart(start), rangeEnd(end)
#endif
{
MOZ_ASSERT(rangeStart <= rangeEnd);
checkSanity();
MOZ_ASSERT(rangeStart <= rangeEnd);
checkSanity();
}
RangedPtr(T* p, T* start, size_t length)
: ptr(p)
@ -111,9 +76,9 @@ class RangedPtr
, rangeStart(start), rangeEnd(start + length)
#endif
{
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
checkSanity();
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
checkSanity();
}
/* Equivalent to RangedPtr(p, p, length). */
@ -123,9 +88,9 @@ class RangedPtr
, rangeStart(p), rangeEnd(p + length)
#endif
{
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
checkSanity();
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
checkSanity();
}
/* Equivalent to RangedPtr(arr, arr, N). */
@ -140,7 +105,7 @@ class RangedPtr
}
T* get() const {
return ptr;
return ptr;
}
/*
@ -154,23 +119,23 @@ class RangedPtr
* p1 = RangedPtr<char>(arr2, 3); // asserts
*/
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
MOZ_ASSERT(rangeStart == other.rangeStart);
MOZ_ASSERT(rangeEnd == other.rangeEnd);
ptr = other.ptr;
checkSanity();
return *this;
MOZ_ASSERT(rangeStart == other.rangeStart);
MOZ_ASSERT(rangeEnd == other.rangeEnd);
ptr = other.ptr;
checkSanity();
return *this;
}
RangedPtr<T> operator+(size_t inc) {
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
MOZ_ASSERT(ptr + inc > ptr);
return create(ptr + inc);
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
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);
return create(ptr - dec);
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
MOZ_ASSERT(ptr - dec < ptr);
return create(ptr - dec);
}
/*
@ -179,97 +144,97 @@ class RangedPtr
*/
template <typename U>
RangedPtr<T>& operator=(U* p) {
*this = create(p);
return *this;
*this = create(p);
return *this;
}
template <typename U>
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
MOZ_ASSERT(rangeStart <= p.ptr);
MOZ_ASSERT(p.ptr <= rangeEnd);
ptr = p.ptr;
checkSanity();
return *this;
MOZ_ASSERT(rangeStart <= p.ptr);
MOZ_ASSERT(p.ptr <= rangeEnd);
ptr = p.ptr;
checkSanity();
return *this;
}
RangedPtr<T>& operator++() {
return (*this += 1);
return (*this += 1);
}
RangedPtr<T> operator++(int) {
RangedPtr<T> rcp = *this;
++*this;
return rcp;
RangedPtr<T> rcp = *this;
++*this;
return rcp;
}
RangedPtr<T>& operator--() {
return (*this -= 1);
return (*this -= 1);
}
RangedPtr<T> operator--(int) {
RangedPtr<T> rcp = *this;
--*this;
return rcp;
RangedPtr<T> rcp = *this;
--*this;
return rcp;
}
RangedPtr<T>& operator+=(size_t inc) {
this->operator=<T>(*this + inc);
return *this;
*this = *this + inc;
return *this;
}
RangedPtr<T>& operator-=(size_t dec) {
this->operator=<T>(*this - dec);
return *this;
*this = *this - dec;
return *this;
}
T& operator[](int index) const {
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
return *create(ptr + index);
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
return *create(ptr + index);
}
T& operator*() const {
return *ptr;
return *ptr;
}
template <typename U>
bool operator==(const RangedPtr<U>& other) const {
return ptr == other.ptr;
return ptr == other.ptr;
}
template <typename U>
bool operator!=(const RangedPtr<U>& other) const {
return !(*this == other);
return !(*this == other);
}
template<typename U>
bool operator==(const U* u) const {
return ptr == u;
return ptr == u;
}
template<typename U>
bool operator!=(const U* u) const {
return !(*this == u);
return !(*this == u);
}
template <typename U>
bool operator<(const RangedPtr<U>& other) const {
return ptr < other.ptr;
return ptr < other.ptr;
}
template <typename U>
bool operator<=(const RangedPtr<U>& other) const {
return ptr <= other.ptr;
return ptr <= other.ptr;
}
template <typename U>
bool operator>(const RangedPtr<U>& other) const {
return ptr > other.ptr;
return ptr > other.ptr;
}
template <typename U>
bool operator>=(const RangedPtr<U>& other) const {
return ptr >= other.ptr;
return ptr >= other.ptr;
}
size_t operator-(const RangedPtr<T>& other) const {
MOZ_ASSERT(ptr >= other.ptr);
return PointerRangeSize(other.ptr, ptr);
MOZ_ASSERT(ptr >= other.ptr);
return PointerRangeSize(other.ptr, ptr);
}
private:

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Jones <jones.chris.g@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* Helpers for defining and using refcounted objects. */
@ -80,24 +45,24 @@ class RefCounted
{
friend class RefPtr<T>;
public:
public:
RefCounted() : refCnt(0) { }
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
// Compatibility with nsRefPtr.
void AddRef() {
MOZ_ASSERT(refCnt >= 0);
++refCnt;
MOZ_ASSERT(refCnt >= 0);
++refCnt;
}
void Release() {
MOZ_ASSERT(refCnt > 0);
if (0 == --refCnt) {
MOZ_ASSERT(refCnt > 0);
if (0 == --refCnt) {
#ifdef DEBUG
refCnt = -0xdead;
refCnt = -0xdead;
#endif
delete static_cast<T*>(this);
}
delete static_cast<T*>(this);
}
}
// Compatibility with wtf::RefPtr.
@ -105,11 +70,11 @@ public:
void deref() { Release(); }
int refCount() const { return refCnt; }
bool hasOneRef() const {
MOZ_ASSERT(refCnt > 0);
return refCnt == 1;
MOZ_ASSERT(refCnt > 0);
return refCnt == 1;
}
private:
private:
int refCnt;
};
@ -130,9 +95,9 @@ class RefPtr
friend class TemporaryRef<T>;
friend class OutParamRef<T>;
struct dontRef {};
struct DontRef {};
public:
public:
RefPtr() : ptr(0) { }
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
@ -144,28 +109,28 @@ public:
~RefPtr() { unref(ptr); }
RefPtr& operator=(const RefPtr& o) {
assign(ref(o.ptr));
return *this;
assign(ref(o.ptr));
return *this;
}
RefPtr& operator=(const TemporaryRef<T>& o) {
assign(o.drop());
return *this;
assign(o.drop());
return *this;
}
RefPtr& operator=(T* t) {
assign(ref(t));
return *this;
assign(ref(t));
return *this;
}
template<typename U>
RefPtr& operator=(const RefPtr<U>& o) {
assign(ref(o.get()));
return *this;
assign(ref(o.get()));
return *this;
}
TemporaryRef<T> forget() {
T* tmp = ptr;
ptr = 0;
return TemporaryRef<T>(tmp, dontRef());
T* tmp = ptr;
ptr = 0;
return TemporaryRef<T>(tmp, DontRef());
}
T* get() const { return ptr; }
@ -175,25 +140,23 @@ public:
template<typename U>
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
private:
private:
void assign(T* t) {
unref(ptr);
ptr = t;
unref(ptr);
ptr = t;
}
T* ptr;
static MOZ_ALWAYS_INLINE T* ref(T* t) {
if (t) {
t->AddRef();
}
return t;
if (t)
t->AddRef();
return t;
}
static MOZ_ALWAYS_INLINE void unref(T* t) {
if (t) {
t->Release();
}
if (t)
t->Release();
}
};
@ -209,9 +172,9 @@ class TemporaryRef
// To allow it to construct TemporaryRef from a bare T*
friend class RefPtr<T>;
typedef typename RefPtr<T>::dontRef dontRef;
typedef typename RefPtr<T>::DontRef DontRef;
public:
public:
TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
@ -221,18 +184,18 @@ public:
~TemporaryRef() { RefPtr<T>::unref(ptr); }
T* drop() const {
T* tmp = ptr;
ptr = 0;
return tmp;
T* tmp = ptr;
ptr = 0;
return tmp;
}
private:
TemporaryRef(T* t, const dontRef&) : ptr(t) {}
private:
TemporaryRef(T* t, const DontRef&) : ptr(t) {}
mutable T* ptr;
TemporaryRef();
TemporaryRef& operator=(const TemporaryRef&);
TemporaryRef() MOZ_DELETE;
void operator=(const TemporaryRef&) MOZ_DELETE;
};
/**
@ -254,15 +217,15 @@ class OutParamRef
{
friend OutParamRef byRef<T>(RefPtr<T>&);
public:
public:
~OutParamRef() {
RefPtr<T>::unref(refPtr.ptr);
refPtr.ptr = tmp;
RefPtr<T>::unref(refPtr.ptr);
refPtr.ptr = tmp;
}
operator T**() { return &tmp; }
private:
private:
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
RefPtr<T>& refPtr;
@ -279,7 +242,7 @@ template<typename T>
OutParamRef<T>
byRef(RefPtr<T>& ptr)
{
return OutParamRef<T>(ptr);
return OutParamRef<T>(ptr);
}
} // namespace mozilla
@ -297,15 +260,15 @@ using namespace mozilla;
struct Foo : public RefCounted<Foo>
{
Foo() : dead(false) { }
~Foo() {
MOZ_ASSERT(!dead);
dead = true;
numDestroyed++;
}
Foo() : dead(false) { }
~Foo() {
MOZ_ASSERT(!dead);
dead = true;
numDestroyed++;
}
bool dead;
static int numDestroyed;
bool dead;
static int numDestroyed;
};
int Foo::numDestroyed;
@ -314,34 +277,34 @@ struct Bar : public Foo { };
TemporaryRef<Foo>
NewFoo()
{
return RefPtr<Foo>(new Foo());
return RefPtr<Foo>(new Foo());
}
TemporaryRef<Foo>
NewBar()
{
return new Bar();
return new Bar();
}
void
GetNewFoo(Foo** f)
{
*f = new Bar();
// Kids, don't try this at home
(*f)->AddRef();
*f = new Bar();
// Kids, don't try this at home
(*f)->AddRef();
}
void
GetPassedFoo(Foo** f)
{
// Kids, don't try this at home
(*f)->AddRef();
// Kids, don't try this at home
(*f)->AddRef();
}
void
GetNewFoo(RefPtr<Foo>* f)
{
*f = new Bar();
*f = new Bar();
}
void
@ -351,93 +314,93 @@ GetPassedFoo(RefPtr<Foo>* f)
TemporaryRef<Foo>
GetNullFoo()
{
return 0;
return 0;
}
int
main(int argc, char** argv)
{
// This should blow up
// This should blow up
// Foo* f = new Foo(); delete f;
MOZ_ASSERT(0 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
MOZ_ASSERT(f->refCount() == 1);
}
MOZ_ASSERT(0 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
MOZ_ASSERT(f->refCount() == 1);
}
MOZ_ASSERT(1 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = NewFoo();
RefPtr<Foo> f2(NewFoo());
MOZ_ASSERT(1 == Foo::numDestroyed);
}
MOZ_ASSERT(3 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = NewFoo();
RefPtr<Foo> f2(NewFoo());
MOZ_ASSERT(1 == Foo::numDestroyed);
}
{
RefPtr<Foo> b = NewBar();
MOZ_ASSERT(3 == Foo::numDestroyed);
}
MOZ_ASSERT(4 == Foo::numDestroyed);
{
RefPtr<Foo> f1;
{
RefPtr<Foo> b = NewBar();
MOZ_ASSERT(3 == Foo::numDestroyed);
f1 = new Foo();
RefPtr<Foo> f2(f1);
RefPtr<Foo> f3 = f2;
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(5 == Foo::numDestroyed);
{
RefPtr<Foo> f1;
{
f1 = new Foo();
RefPtr<Foo> f2(f1);
RefPtr<Foo> f3 = f2;
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(4 == Foo::numDestroyed);
}
MOZ_ASSERT(5 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
f.forget();
MOZ_ASSERT(6 == Foo::numDestroyed);
}
{
RefPtr<Foo> f = new Foo();
f.forget();
MOZ_ASSERT(6 == Foo::numDestroyed);
}
{
RefPtr<Foo> f = new Foo();
GetNewFoo(byRef(f));
MOZ_ASSERT(7 == Foo::numDestroyed);
}
MOZ_ASSERT(8 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetNewFoo(byRef(f));
MOZ_ASSERT(7 == Foo::numDestroyed);
}
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(byRef(f));
MOZ_ASSERT(8 == Foo::numDestroyed);
}
MOZ_ASSERT(9 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(byRef(f));
MOZ_ASSERT(8 == Foo::numDestroyed);
}
MOZ_ASSERT(9 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetNewFoo(&f);
MOZ_ASSERT(10 == Foo::numDestroyed);
}
MOZ_ASSERT(11 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetNewFoo(&f);
MOZ_ASSERT(10 == Foo::numDestroyed);
}
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(&f);
MOZ_ASSERT(11 == Foo::numDestroyed);
}
MOZ_ASSERT(12 == Foo::numDestroyed);
{
RefPtr<Foo> f = new Foo();
GetPassedFoo(&f);
MOZ_ASSERT(11 == Foo::numDestroyed);
}
MOZ_ASSERT(12 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = new Bar();
}
MOZ_ASSERT(13 == Foo::numDestroyed);
{
RefPtr<Foo> f1 = new Bar();
}
{
RefPtr<Foo> f = GetNullFoo();
MOZ_ASSERT(13 == Foo::numDestroyed);
}
MOZ_ASSERT(13 == Foo::numDestroyed);
{
RefPtr<Foo> f = GetNullFoo();
MOZ_ASSERT(13 == Foo::numDestroyed);
}
MOZ_ASSERT(13 == Foo::numDestroyed);
return 0;
return 0;
}
#endif

View File

@ -35,12 +35,12 @@
* Note that the RAII classes defined in this header do _not_ perform any form
* of reference-counting or garbage-collection. These classes have exactly two
* behaviors:
*
* - if |forget()| has not been called, the resource is always deallocated at
* the end of the scope;
* - if |forget()| has been called, any control on the resource is unbound
* and the resource is not deallocated by the class.
*
*
* Extension:
*
* In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
@ -52,6 +52,8 @@
#include "mozilla/Attributes.h"
#include "mozilla/GuardObjects.h"
namespace mozilla {
/*
* Scoped is a helper to create RAII wrappers
* Type argument |Traits| is expected to have the following structure:
@ -66,87 +68,87 @@
* const static void release(type);
* }
*/
template <typename Traits>
template<typename Traits>
class Scoped
{
public:
typedef typename Traits::type Resource;
public:
typedef typename Traits::type Resource;
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
: value(Traits::empty())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
explicit Scoped(const Resource& value
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: value(value)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~Scoped() {
Traits::release(value);
}
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
: value(Traits::empty())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
explicit Scoped(const Resource& value
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: value(value)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~Scoped() {
Traits::release(value);
}
// Constant getter
operator const Resource&() const { return value; }
const Resource& operator->() const { return value; }
const Resource& get() const { return value; }
// Non-constant getter.
Resource& rwget() { return value; }
// Constant getter
operator const Resource&() const { return value; }
const Resource& operator->() const { return value; }
const Resource& get() const { return value; }
// Non-constant getter.
Resource& rwget() { return value; }
/*
* Forget the resource.
*
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
* have no effect at destruction (unless it is reset to another resource by
* |operator=|).
*
* @return The original resource.
*/
Resource forget() {
Resource tmp = value;
value = Traits::empty();
return tmp;
}
/*
* Forget the resource.
*
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
* have no effect at destruction (unless it is reset to another resource by
* |operator=|).
*
* @return The original resource.
*/
Resource forget() {
Resource tmp = value;
value = Traits::empty();
return tmp;
}
/*
* Perform immediate clean-up of this |Scoped|.
*
* If this |Scoped| is currently empty, this method has no effect.
*/
void dispose() {
Traits::release(value);
value = Traits::empty();
}
/*
* Perform immediate clean-up of this |Scoped|.
*
* If this |Scoped| is currently empty, this method has no effect.
*/
void dispose() {
Traits::release(value);
value = Traits::empty();
}
bool operator==(const Resource& other) const {
return value == other;
}
bool operator==(const Resource& other) const {
return value == other;
}
/*
* Replace the resource with another resource.
*
* Calling |operator=| has the side-effect of triggering clean-up. If you do
* not want to trigger clean-up, you should first invoke |forget|.
*
* @return this
*/
Scoped<Traits>& operator=(const Resource& other) {
return reset(other);
}
Scoped<Traits>& reset(const Resource& other) {
Traits::release(value);
value = other;
return *this;
}
/*
* Replace the resource with another resource.
*
* Calling |operator=| has the side-effect of triggering clean-up. If you do
* not want to trigger clean-up, you should first invoke |forget|.
*
* @return this
*/
Scoped<Traits>& operator=(const Resource& other) {
return reset(other);
}
Scoped<Traits>& reset(const Resource& other) {
Traits::release(value);
value = other;
return *this;
}
private:
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
private:
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
private:
Resource value;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
private:
Resource value;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/*
@ -158,25 +160,25 @@ private:
* for more details.
*/
#define SCOPED_TEMPLATE(name, Traits) \
template <typename Type> \
struct name : public Scoped<Traits<Type> > \
template<typename Type> \
struct name : public mozilla::Scoped<Traits<Type> > \
{ \
typedef Scoped<Traits<Type> > Super; \
typedef typename Super::Resource Resource; \
name& operator=(Resource ptr) { \
Super::operator=(ptr); \
return *this; \
} \
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
{} \
explicit name(Resource ptr \
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
{} \
private: \
explicit name(name& source) MOZ_DELETE; \
name& operator=(name& source) MOZ_DELETE; \
typedef mozilla::Scoped<Traits<Type> > Super; \
typedef typename Super::Resource Resource; \
name& operator=(Resource ptr) { \
Super::operator=(ptr); \
return *this; \
} \
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
{} \
explicit name(Resource ptr \
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
{} \
private: \
explicit name(name& source) MOZ_DELETE; \
name& operator=(name& source) MOZ_DELETE; \
};
/*
@ -186,12 +188,12 @@ private: \
* ScopedFreePtr<S> foo = malloc(sizeof(S));
* ScopedFreePtr<char> bar = strdup(str);
*/
template <typename T>
template<typename T>
struct ScopedFreePtrTraits
{
typedef T* type;
static T* empty() { return NULL; }
static void release(T* ptr) { free(ptr); }
typedef T* type;
static T* empty() { return NULL; }
static void release(T* ptr) { free(ptr); }
};
SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
@ -201,9 +203,10 @@ SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
* struct S { ... };
* ScopedDeletePtr<S> foo = new S();
*/
template <typename T>
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T> {
static void release(T* ptr) { delete ptr; }
template<typename T>
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T>
{
static void release(T* ptr) { delete ptr; }
};
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
@ -213,12 +216,13 @@ SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
* struct S { ... };
* ScopedDeleteArray<S> foo = new S[42];
*/
template <typename T>
template<typename T>
struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
{
static void release(T* ptr) { delete [] ptr; }
static void release(T* ptr) { delete [] ptr; }
};
SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
} /* namespace mozilla */
#endif // mozilla_Scoped_h_

View File

@ -1,42 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* Implements the C99 <stdint.h> interface for C and C++ code. */

View File

@ -0,0 +1,144 @@
/* -*- 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/. */
/* Cross-platform lightweight thread local data wrappers. */
#ifndef mozilla_TLS_h_
#define mozilla_TLS_h_
#if defined(XP_WIN)
// This file will get included in any file that wants to add a profiler mark.
// In order to not bring <windows.h> together we could include windef.h and
// winbase.h which are sufficient to get the prototypes for the Tls* functions.
// # include <windef.h>
// # include <winbase.h>
// Unfortunately, even including these headers causes us to add a bunch of ugly
// stuff to our namespace e.g #define CreateEvent CreateEventW
extern "C" {
__declspec(dllimport) void * __stdcall TlsGetValue(unsigned long);
__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void *);
__declspec(dllimport) unsigned long __stdcall TlsAlloc();
}
#else
# include <pthread.h>
# include <signal.h>
#endif
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
namespace mozilla {
// sig_safe_t denotes an atomic type which can be read or stored in a single
// instruction. This means that data of this type is safe to be manipulated
// from a signal handler, or other similar asynchronous execution contexts.
#if defined(XP_WIN)
typedef unsigned long sig_safe_t;
#else
typedef sig_atomic_t sig_safe_t;
#endif
/*
* Thread Local Storage helpers.
*
* Usage:
*
* Only static-storage-duration (e.g. global variables, or static class members)
* objects of this class should be instantiated. This class relies on
* zero-initialization, which is implicit for static-storage-duration objects.
* It doesn't have a custom default constructor, to avoid static initializers.
*
* API usage:
*
* // Create a TLS item
* mozilla::ThreadLocal<int> tlsKey;
* if (!tlsKey.init()) {
* // deal with the error
* }
*
* // Set the TLS value
* tlsKey.set(123);
*
* // Get the TLS value
* int value = tlsKey.get();
*/
template<typename T>
class ThreadLocal
{
#if defined(XP_WIN)
typedef unsigned long key_t;
#else
typedef pthread_key_t key_t;
#endif
union Helper {
void* ptr;
T value;
};
public:
MOZ_WARN_UNUSED_RESULT inline bool init();
inline T get() const;
inline bool set(const T value);
bool initialized() const {
return inited;
}
private:
key_t key;
bool inited;
};
template<typename T>
inline bool
ThreadLocal<T>::init()
{
MOZ_STATIC_ASSERT(sizeof(T) <= sizeof(void *),
"mozilla::ThreadLocal can't be used for types larger than "
"a pointer");
MOZ_ASSERT(!initialized());
#ifdef XP_WIN
key = TlsAlloc();
inited = key != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#else
inited = !pthread_key_create(&key, NULL);
#endif
return inited;
}
template<typename T>
inline T
ThreadLocal<T>::get() const
{
MOZ_ASSERT(initialized());
Helper h;
#ifdef XP_WIN
h.ptr = TlsGetValue(key);
#else
h.ptr = pthread_getspecific(key);
#endif
return h.value;
}
template<typename T>
inline bool
ThreadLocal<T>::set(const T value)
{
MOZ_ASSERT(initialized());
Helper h;
h.value = value;
#ifdef XP_WIN
return TlsSetValue(key, h.ptr);
#else
return !pthread_setspecific(key, h.ptr);
#endif
}
} // namespace mozilla
#endif // mozilla_TLS_h_

View File

@ -0,0 +1,122 @@
/* 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/. */
/* Template-based metaprogramming and type-testing facilities. */
#ifndef mozilla_TypeTraits_h_
#define mozilla_TypeTraits_h_
namespace mozilla {
/*
* IsBaseOf allows to know whether a given class is derived from another.
*
* Consider the following class definitions:
*
* class A {};
* class B : public A {};
* class C {};
*
* mozilla::IsBaseOf<A, B>::value is true;
* mozilla::IsBaseOf<A, C>::value is false;
*/
template<class Base, class Derived>
class IsBaseOf
{
private:
static char test(Base* b);
static int test(...);
public:
static const bool value =
sizeof(test(static_cast<Derived*>(0))) == sizeof(char);
};
/*
* IsConvertible determines whether a value of type From will implicitly convert
* to a value of type To. For example:
*
* struct A {};
* struct B : public A {};
* struct C {};
*
* mozilla::IsConvertible<A, A>::value is true;
* mozilla::IsConvertible<A*, A*>::value is true;
* mozilla::IsConvertible<B, A>::value is true;
* mozilla::IsConvertible<B*, A*>::value is true;
* mozilla::IsConvertible<C, A>::value is false;
* mozilla::IsConvertible<A, C>::value is false;
* mozilla::IsConvertible<A*, C*>::value is false;
* mozilla::IsConvertible<C*, A*>::value is false.
*
* For obscure reasons, you can't use IsConvertible when the types being tested
* are related through private inheritance, and you'll get a compile error if
* you try. Just don't do it!
*/
template<typename From, typename To>
struct IsConvertible
{
private:
static From create();
template<typename From1, typename To1>
static char test(To to);
template<typename From1, typename To1>
static int test(...);
public:
static const bool value =
sizeof(test<From, To>(create())) == sizeof(char);
};
/*
* Conditional selects a class between two, depending on a given boolean value.
*
* mozilla::Conditional<true, A, B>::Type is A;
* mozilla::Conditional<false, A, B>::Type is B;
*/
template<bool condition, class A, class B>
struct Conditional
{
typedef A Type;
};
template<class A, class B>
struct Conditional<false, A, B>
{
typedef B Type;
};
/*
* EnableIf is a struct containing a typedef of T if and only if B is true.
*
* mozilla::EnableIf<true, int>::Type is int;
* mozilla::EnableIf<false, int>::Type is a compile-time error.
*
* Use this template to implement SFINAE-style (Substitution Failure Is not An
* Error) requirements. For example, you might use it to impose a restriction
* on a template parameter:
*
* template<typename T>
* class PodVector // vector optimized to store POD (memcpy-able) types
* {
* EnableIf<IsPodType<T>, T>::Type* vector;
* size_t length;
* ...
* };
*/
template<bool B, typename T = void>
struct EnableIf
{};
template<typename T>
struct EnableIf<true, T>
{
typedef T Type;
};
} /* namespace mozilla */
#endif /* mozilla_TypeTraits_h_ */

View File

@ -1,41 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/* mfbt foundational types and macros. */

View File

@ -1,41 +1,7 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- 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/. */
/*
* Miscellaneous uncategorized functionality. Please add new functionality to
@ -54,54 +20,53 @@
namespace mozilla {
/**
* DebugOnly contains a value of type T, but only in debug builds. In
* release builds, it does not contain a value. This helper is
* intended to be used along with ASSERT()-style macros, allowing one
* to write
* DebugOnly contains a value of type T, but only in debug builds. In release
* builds, it does not contain a value. This helper is intended to be used with
* MOZ_ASSERT()-style macros, allowing one to write:
*
* DebugOnly<bool> check = Func();
* ASSERT(check);
* DebugOnly<bool> check = func();
* MOZ_ASSERT(check);
*
* more concisely than declaring |check| conditional on #ifdef DEBUG,
* but also without allocating storage space for |check| in release
* builds.
* more concisely than declaring |check| conditional on #ifdef DEBUG, but also
* without allocating storage space for |check| in release builds.
*
* DebugOnly instances can only be coerced to T in debug builds; in
* release builds, they don't have a value so type coercion is not
* well defined.
* DebugOnly instances can only be coerced to T in debug builds. In release
* builds they don't have a value, so type coercion is not well defined.
*/
template <typename T>
template<typename T>
struct DebugOnly
{
#ifdef DEBUG
T value;
DebugOnly() {}
DebugOnly(const T& other) : value(other) {}
DebugOnly(const DebugOnly& other) : value(other.value) {}
DebugOnly() { }
DebugOnly(const T& other) : value(other) { }
DebugOnly(const DebugOnly& other) : value(other.value) { }
DebugOnly& operator=(const T& rhs) {
value = rhs;
return *this;
value = rhs;
return *this;
}
void operator++(int) {
value++;
value++;
}
void operator--(int) {
value--;
value--;
}
T *operator&() { return &value; }
operator T&() { return value; }
operator const T&() const { return value; }
T& operator->() { return value; }
#else
DebugOnly() {}
DebugOnly(const T&) {}
DebugOnly(const DebugOnly&) {}
DebugOnly() { }
DebugOnly(const T&) { }
DebugOnly(const DebugOnly&) { }
DebugOnly& operator=(const T&) { return *this; }
void operator++(int) {}
void operator--(int) {}
void operator++(int) { }
void operator--(int) { }
#endif
/*
@ -117,17 +82,16 @@ struct DebugOnly
* bytes of alignment a given type needs.
*/
template<class T>
struct AlignmentFinder
class AlignmentFinder
{
private:
struct Aligner
{
char c;
T t;
};
struct Aligner
{
char c;
T t;
};
public:
static const int alignment = sizeof(Aligner) - sizeof(T);
public:
static const size_t alignment = sizeof(Aligner) - sizeof(T);
};
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
@ -154,7 +118,8 @@ public:
#endif
/*
* AlignedElem<N> is a structure whose alignment is guaranteed to be at least N bytes.
* AlignedElem<N> is a structure whose alignment is guaranteed to be at least N
* bytes.
*
* We support 1, 2, 4, 8, and 16-bit alignment.
*/
@ -169,31 +134,31 @@ struct AlignedElem;
template<>
struct AlignedElem<1>
{
MOZ_ALIGNED_DECL(uint8_t elem, 1);
MOZ_ALIGNED_DECL(uint8_t elem, 1);
};
template<>
struct AlignedElem<2>
{
MOZ_ALIGNED_DECL(uint8_t elem, 2);
MOZ_ALIGNED_DECL(uint8_t elem, 2);
};
template<>
struct AlignedElem<4>
{
MOZ_ALIGNED_DECL(uint8_t elem, 4);
MOZ_ALIGNED_DECL(uint8_t elem, 4);
};
template<>
struct AlignedElem<8>
{
MOZ_ALIGNED_DECL(uint8_t elem, 8);
MOZ_ALIGNED_DECL(uint8_t elem, 8);
};
template<>
struct AlignedElem<16>
{
MOZ_ALIGNED_DECL(uint8_t elem, 16);
MOZ_ALIGNED_DECL(uint8_t elem, 16);
};
/*
@ -206,28 +171,28 @@ struct AlignedElem<16>
* false negatives when we cast from the char buffer to whatever type we've
* constructed using the bytes.
*/
template <size_t nbytes>
template<size_t nbytes>
struct AlignedStorage
{
union U {
char bytes[nbytes];
uint64_t _;
char bytes[nbytes];
uint64_t _;
} u;
const void *addr() const { return u.bytes; }
void *addr() { return u.bytes; }
const void* addr() const { return u.bytes; }
void* addr() { return u.bytes; }
};
template <class T>
template<class T>
struct AlignedStorage2
{
union U {
char bytes[sizeof(T)];
uint64_t _;
char bytes[sizeof(T)];
uint64_t _;
} u;
const T *addr() const { return (const T *)u.bytes; }
T *addr() { return (T *)(void *)u.bytes; }
const T* addr() const { return reinterpret_cast<const T*>(u.bytes); }
T* addr() { return static_cast<T*>(static_cast<void*>(u.bytes)); }
};
/*
@ -241,16 +206,13 @@ struct AlignedStorage2
* N.B. GCC seems to miss some optimizations with Maybe and may generate extra
* branches/loads/stores. Use with caution on hot paths.
*/
template <class T>
template<class T>
class Maybe
{
AlignedStorage2<T> storage;
bool constructed;
T &asT() { return *storage.addr(); }
explicit Maybe(const Maybe &other);
const Maybe &operator=(const Maybe &other);
T& asT() { return *storage.addr(); }
public:
Maybe() { constructed = false; }
@ -259,63 +221,67 @@ class Maybe
bool empty() const { return !constructed; }
void construct() {
MOZ_ASSERT(!constructed);
new(storage.addr()) T();
constructed = true;
MOZ_ASSERT(!constructed);
new (storage.addr()) T();
constructed = true;
}
template <class T1>
void construct(const T1 &t1) {
MOZ_ASSERT(!constructed);
new(storage.addr()) T(t1);
constructed = true;
template<class T1>
void construct(const T1& t1) {
MOZ_ASSERT(!constructed);
new (storage.addr()) T(t1);
constructed = true;
}
template <class T1, class T2>
void construct(const T1 &t1, const T2 &t2) {
MOZ_ASSERT(!constructed);
new(storage.addr()) T(t1, t2);
constructed = true;
template<class T1, class T2>
void construct(const T1& t1, const T2& t2) {
MOZ_ASSERT(!constructed);
new (storage.addr()) T(t1, t2);
constructed = true;
}
template <class T1, class T2, class T3>
void construct(const T1 &t1, const T2 &t2, const T3 &t3) {
MOZ_ASSERT(!constructed);
new(storage.addr()) T(t1, t2, t3);
constructed = true;
template<class T1, class T2, class T3>
void construct(const T1& t1, const T2& t2, const T3& t3) {
MOZ_ASSERT(!constructed);
new (storage.addr()) T(t1, t2, t3);
constructed = true;
}
template <class T1, class T2, class T3, class T4>
void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) {
MOZ_ASSERT(!constructed);
new(storage.addr()) T(t1, t2, t3, t4);
constructed = true;
template<class T1, class T2, class T3, class T4>
void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
MOZ_ASSERT(!constructed);
new (storage.addr()) T(t1, t2, t3, t4);
constructed = true;
}
T *addr() {
MOZ_ASSERT(constructed);
return &asT();
T* addr() {
MOZ_ASSERT(constructed);
return &asT();
}
T &ref() {
MOZ_ASSERT(constructed);
return asT();
T& ref() {
MOZ_ASSERT(constructed);
return asT();
}
const T &ref() const {
MOZ_ASSERT(constructed);
return const_cast<Maybe *>(this)->asT();
const T& ref() const {
MOZ_ASSERT(constructed);
return const_cast<Maybe*>(this)->asT();
}
void destroy() {
ref().~T();
constructed = false;
ref().~T();
constructed = false;
}
void destroyIfConstructed() {
if (!empty())
destroy();
if (!empty())
destroy();
}
private:
Maybe(const Maybe& other) MOZ_DELETE;
const Maybe& operator=(const Maybe& other) MOZ_DELETE;
};
/*
@ -324,12 +290,12 @@ class Maybe
* set, the unsigned subtraction followed by right shift will produce -1, or
* size_t(-1), instead of the real difference.
*/
template <class T>
template<class T>
MOZ_ALWAYS_INLINE size_t
PointerRangeSize(T* begin, T* end)
{
MOZ_ASSERT(end >= begin);
return (size_t(end) - size_t(begin)) / sizeof(T);
MOZ_ASSERT(end >= begin);
return (size_t(end) - size_t(begin)) / sizeof(T);
}
/*
@ -342,7 +308,7 @@ template<typename T, size_t N>
size_t
ArrayLength(T (&arr)[N])
{
return N;
return N;
}
/*
@ -354,7 +320,7 @@ template<typename T, size_t N>
T*
ArrayEnd(T (&arr)[N])
{
return arr + ArrayLength(arr);
return arr + ArrayLength(arr);
}
} /* namespace mozilla */

View File

@ -1 +1 @@
29c015353614a093d22d1bee3429e9188d368789
520bea66db801ee6ba7a86ca8974c3999fdc0a30

View File

@ -1 +1 @@
8754a55b4cfc1c5e9d997ae3ed037cdfd5943c6c
3fc46b3f219996b838b31afe55827e2803dd1f48