mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 612150 - Eliminating JS_GetFunctionName. r=mrbkap
This commit is contained in:
parent
01067dbf04
commit
3717953163
@ -273,7 +273,7 @@ struct JSDValue
|
||||
intN nref;
|
||||
JSCList props;
|
||||
JSString* string;
|
||||
const char* funName;
|
||||
JSString* funName;
|
||||
const char* className;
|
||||
JSDValue* proto;
|
||||
JSDValue* parent;
|
||||
@ -460,7 +460,7 @@ jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript);
|
||||
extern const char*
|
||||
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript);
|
||||
|
||||
extern const char*
|
||||
extern JSString*
|
||||
jsd_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript);
|
||||
|
||||
extern uintN
|
||||
@ -724,7 +724,7 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe);
|
||||
|
||||
extern const char*
|
||||
extern JSString*
|
||||
jsd_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe);
|
||||
@ -969,7 +969,7 @@ jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
|
||||
extern JSString*
|
||||
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
|
||||
|
||||
extern const char*
|
||||
extern JSString*
|
||||
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval);
|
||||
|
||||
/**************************************************/
|
||||
|
@ -197,22 +197,29 @@ static void
|
||||
_dumpJSDScript(JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
||||
{
|
||||
const char* name;
|
||||
const char* fun;
|
||||
JSString* fun;
|
||||
uintN base;
|
||||
uintN extent;
|
||||
char Buf[256];
|
||||
|
||||
size_t n;
|
||||
|
||||
name = jsd_GetScriptFilename(jsdc, jsdscript);
|
||||
fun = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
||||
base = jsd_GetScriptBaseLineNumber(jsdc, jsdscript);
|
||||
extent = jsd_GetScriptLineExtent(jsdc, jsdscript);
|
||||
|
||||
sprintf( Buf, "%sscript=%08X, %s, %s, %d-%d\n",
|
||||
leadingtext,
|
||||
(unsigned) jsdscript->script,
|
||||
name ? name : "no URL",
|
||||
fun ? fun : "no fun",
|
||||
base, base + extent - 1 );
|
||||
n = size_t(snprintf(Buf, sizeof(Buf), "%sscript=%08X, %s, ",
|
||||
leadingtext, (unsigned) jsdscript->script,
|
||||
name ? name : "no URL"));
|
||||
if (n + 1 < sizeof(Buf)) {
|
||||
if (fun) {
|
||||
n += size_t(snprintf(Buf + n, sizeof(Buf) - n, "%s", "no fun"));
|
||||
} else {
|
||||
n += JS_PutEscapedString(Buf + n, sizeof(Buf) - n, fun, 0);
|
||||
Buf[sizeof(Buf) - 1] = '\0';
|
||||
}
|
||||
if (n + 1 < sizeof(Buf))
|
||||
snprintf(Buf + n, sizeof(Buf) - n, ", %d-%d\n", base, base + extent - 1);
|
||||
}
|
||||
OutputDebugString( Buf );
|
||||
}
|
||||
|
||||
@ -488,12 +495,15 @@ jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
return jsdscript->url;
|
||||
}
|
||||
|
||||
const char*
|
||||
JSString*
|
||||
jsd_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
JSString* str;
|
||||
|
||||
if( ! jsdscript->function )
|
||||
return NULL;
|
||||
return JS_GetFunctionName(jsdscript->function);
|
||||
str = JS_GetFunctionId(jsdscript->function);
|
||||
return str ? str : JS_GetEmptyString(jsdc->jsrt);
|
||||
}
|
||||
|
||||
uintN
|
||||
|
@ -356,12 +356,12 @@ jsd_GetThisForStackFrame(JSDContext* jsdc,
|
||||
return jsdval;
|
||||
}
|
||||
|
||||
const char*
|
||||
JSString*
|
||||
jsd_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
{
|
||||
const char *rv = NULL;
|
||||
JSString *rv = NULL;
|
||||
|
||||
JSD_LOCK_THREADSTATES(jsdc);
|
||||
|
||||
@ -370,7 +370,7 @@ jsd_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSFunction *fun = JS_GetFrameFunction (jsdthreadstate->context,
|
||||
jsdframe->fp);
|
||||
if (fun)
|
||||
rv = JS_GetFunctionName (fun);
|
||||
rv = JS_GetFunctionId (fun);
|
||||
}
|
||||
|
||||
JSD_UNLOCK_THREADSTATES(jsdc);
|
||||
|
@ -69,7 +69,7 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
||||
JSDScript* jsdscript = NULL;
|
||||
JSScript * script;
|
||||
static indent = 0;
|
||||
const char* funName = NULL;
|
||||
JSString* funName = NULL;
|
||||
|
||||
script = JS_GetFrameScript(cx, fp);
|
||||
if(script)
|
||||
@ -80,27 +80,29 @@ _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
|
||||
if(jsdscript)
|
||||
funName = JSD_GetScriptFunctionName(jsdc, jsdscript);
|
||||
}
|
||||
if(!funName)
|
||||
funName = "TOP_LEVEL";
|
||||
|
||||
if(before)
|
||||
printf("%sentering ", _indentSpaces(indent++));
|
||||
else
|
||||
printf("%sleaving ", _indentSpaces(--indent));
|
||||
|
||||
if (!funName)
|
||||
printf("TOP_LEVEL");
|
||||
else
|
||||
JS_FileEscapedString(stdout, funName, 0);
|
||||
|
||||
if(before)
|
||||
{
|
||||
jsval thisVal;
|
||||
|
||||
printf("%sentering %s %s this: ",
|
||||
_indentSpaces(indent++),
|
||||
funName,
|
||||
JS_IsConstructorFrame(cx, fp) ? "constructing":"");
|
||||
printf("%s this: ", JS_IsConstructorFrame(cx, fp) ? "constructing":"");
|
||||
|
||||
if (JS_GetFrameThis(cx, fp, &thisVal))
|
||||
printf("0x%0llx\n", (JSUword) thisVal);
|
||||
printf("0x%0llx", (JSUword) thisVal);
|
||||
else
|
||||
puts("<unavailable>");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%sleaving %s\n", _indentSpaces(--indent), funName);
|
||||
}
|
||||
printf("\n");
|
||||
JS_ASSERT(indent >= 0);
|
||||
}
|
||||
#endif
|
||||
|
@ -246,7 +246,7 @@ jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||
return jsdval->string;
|
||||
}
|
||||
|
||||
const char*
|
||||
JSString*
|
||||
jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSContext* cx = jsdc->dumbContext;
|
||||
@ -272,7 +272,9 @@ jsd_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
|
||||
JS_EndRequest(cx);
|
||||
if(!fun)
|
||||
return NULL;
|
||||
jsdval->funName = JS_GetFunctionName(fun);
|
||||
jsdval->funName = JS_GetFunctionId(fun);
|
||||
if (!jsdval->funName)
|
||||
jsdval->funName = JS_GetEmptyString(jsdc->jsrt);
|
||||
}
|
||||
return jsdval->funName;
|
||||
}
|
||||
|
@ -953,6 +953,23 @@ jsdProperty::GetVarArgSlot(PRUint32 *_rval)
|
||||
/* Scripts */
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
|
||||
|
||||
static NS_IMETHODIMP
|
||||
AssignToJSString(nsACString *x, JSString *str)
|
||||
{
|
||||
if (!str) {
|
||||
x->SetLength(0);
|
||||
return NS_OK;
|
||||
}
|
||||
size_t length = JS_GetStringEncodingLength(NULL, str);
|
||||
if (length == size_t(-1))
|
||||
return NS_ERROR_FAILURE;
|
||||
x->SetLength(PRUint32(length));
|
||||
if (x->Length() != PRUint32(length))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_EncodeStringToBuffer(str, x->BeginWriting(), length);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
|
||||
mTag(0),
|
||||
mCx(aCx),
|
||||
@ -971,8 +988,12 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(PR_FALSE),
|
||||
* gets destroyed. */
|
||||
JSD_LockScriptSubsystem(mCx);
|
||||
mFileName = new nsCString(JSD_GetScriptFilename(mCx, mScript));
|
||||
mFunctionName =
|
||||
new nsCString(JSD_GetScriptFunctionName(mCx, mScript));
|
||||
mFunctionName = new nsCString();
|
||||
if (mFunctionName) {
|
||||
JSString *str = JSD_GetScriptFunctionName(mCx, mScript);
|
||||
if (str)
|
||||
AssignToJSString(mFunctionName, str);
|
||||
}
|
||||
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
||||
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
|
||||
mFirstPC = JSD_GetClosestPC(mCx, mScript, 0);
|
||||
@ -1844,7 +1865,11 @@ NS_IMETHODIMP
|
||||
jsdStackFrame::GetFunctionName(nsACString &_rval)
|
||||
{
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
_rval.Assign(JSD_GetNameForStackFrame(mCx, mThreadState, mStackFrameInfo));
|
||||
JSString *str = JSD_GetNameForStackFrame(mCx, mThreadState, mStackFrameInfo);
|
||||
if (str)
|
||||
return AssignToJSString(&_rval, str);
|
||||
|
||||
_rval.Assign("anonymous");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2172,8 +2197,7 @@ NS_IMETHODIMP
|
||||
jsdValue::GetJsFunctionName(nsACString &_rval)
|
||||
{
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
_rval.Assign(JSD_GetValueFunctionName(mCx, mValue));
|
||||
return NS_OK;
|
||||
return AssignToJSString(&_rval, JSD_GetValueFunctionName(mCx, mValue));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -302,7 +302,7 @@ JSD_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
return jsd_GetScriptFilename(jsdc, jsdscript);
|
||||
}
|
||||
|
||||
JSD_PUBLIC_API(const char*)
|
||||
JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript)
|
||||
{
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
@ -741,7 +741,7 @@ JSD_GetThisForStackFrame(JSDContext* jsdc,
|
||||
return jsd_GetThisForStackFrame(jsdc, jsdthreadstate, jsdframe);
|
||||
}
|
||||
|
||||
JSD_PUBLIC_API(const char*)
|
||||
JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe)
|
||||
@ -1108,7 +1108,7 @@ JSD_GetValueString(JSDContext* jsdc, JSDValue* jsdval)
|
||||
return jsd_GetValueString(jsdc, jsdval);
|
||||
}
|
||||
|
||||
JSD_PUBLIC_API(const char*)
|
||||
JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval)
|
||||
{
|
||||
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
||||
|
@ -429,9 +429,10 @@ extern JSD_PUBLIC_API(const char*)
|
||||
JSD_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript);
|
||||
|
||||
/*
|
||||
* Get the function name associated with this script (NULL if not a function)
|
||||
* Get the function name associated with this script (NULL if not a function).
|
||||
* If the function does not have a name the result is an empty string.
|
||||
*/
|
||||
extern JSD_PUBLIC_API(const char*)
|
||||
extern JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript);
|
||||
|
||||
/*
|
||||
@ -955,7 +956,7 @@ JSD_GetThisForStackFrame(JSDContext* jsdc,
|
||||
* Get the name of the function executing in this stack frame. Especially useful
|
||||
* for native frames (without script objects.)
|
||||
*/
|
||||
extern JSD_PUBLIC_API(const char*)
|
||||
extern JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetNameForStackFrame(JSDContext* jsdc,
|
||||
JSDThreadState* jsdthreadstate,
|
||||
JSDStackFrameInfo* jsdframe);
|
||||
@ -1288,7 +1289,7 @@ JSD_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
|
||||
* Return name of function IFF JSDValue represents a function.
|
||||
* *** new for version 1.1 ****
|
||||
*/
|
||||
extern JSD_PUBLIC_API(const char*)
|
||||
extern JSD_PUBLIC_API(JSString *)
|
||||
JSD_GetValueFunctionName(JSDContext* jsdc, JSDValue* jsdval);
|
||||
|
||||
/**************************************************/
|
||||
|
@ -202,6 +202,13 @@ JS_GetEmptyStringValue(JSContext *cx)
|
||||
return STRING_TO_JSVAL(cx->runtime->emptyString);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
JS_GetEmptyString(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt->state == JSRTS_UP);
|
||||
return rt->emptyString;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, jsval **vpp, va_list *app)
|
||||
{
|
||||
@ -634,10 +641,6 @@ JSRuntime::init(uint32 maxbytes)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
deflatedStringCache = new js::DeflatedStringCache();
|
||||
if (!deflatedStringCache || !deflatedStringCache->init())
|
||||
return false;
|
||||
|
||||
wrapObjectCallback = js::TransparentObjectWrapper;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
@ -683,11 +686,6 @@ JSRuntime::~JSRuntime()
|
||||
js_FreeRuntimeScriptState(this);
|
||||
js_FinishAtomState(this);
|
||||
|
||||
/*
|
||||
* Finish the deflated string cache after the last GC and after
|
||||
* calling js_FinishAtomState, which finalizes strings.
|
||||
*/
|
||||
delete deflatedStringCache;
|
||||
#if ENABLE_YARR_JIT
|
||||
delete regExpAllocator;
|
||||
#endif
|
||||
@ -4212,15 +4210,6 @@ JS_GetFunctionObject(JSFunction *fun)
|
||||
return FUN_OBJECT(fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_GetFunctionName(JSFunction *fun)
|
||||
{
|
||||
if (!fun->atom)
|
||||
return js_anonymous_str;
|
||||
const char *byte = js_GetStringBytes(fun->atom);
|
||||
return byte ? byte : "";
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString *)
|
||||
JS_GetFunctionId(JSFunction *fun)
|
||||
{
|
||||
|
@ -545,6 +545,9 @@ JS_GetPositiveInfinityValue(JSContext *cx);
|
||||
extern JS_PUBLIC_API(jsval)
|
||||
JS_GetEmptyStringValue(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_GetEmptyString(JSRuntime *rt);
|
||||
|
||||
/*
|
||||
* Format is a string of the following characters (spaces are insignificant),
|
||||
* specifying the tabulated type conversions:
|
||||
@ -2339,22 +2342,11 @@ JS_NewFunctionById(JSContext *cx, JSNative call, uintN nargs, uintN flags,
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFunctionObject(JSFunction *fun);
|
||||
|
||||
/*
|
||||
* Deprecated, useful only for diagnostics. Use JS_GetFunctionId instead for
|
||||
* anonymous vs. "anonymous" disambiguation and Unicode fidelity.
|
||||
*/
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetFunctionName(JSFunction *fun);
|
||||
|
||||
/*
|
||||
* Return the function's identifier as a JSString, or null if fun is unnamed.
|
||||
* The returned string lives as long as fun, so you don't need to root a saved
|
||||
* reference to it if fun is well-connected or rooted, and provided you bound
|
||||
* the use of the saved reference by fun's lifetime.
|
||||
*
|
||||
* Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for
|
||||
* truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars
|
||||
* from UTF-16-ish jschars.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_GetFunctionId(JSFunction *fun);
|
||||
|
@ -1369,8 +1369,6 @@ struct JSRuntime {
|
||||
js::Value negativeInfinityValue;
|
||||
js::Value positiveInfinityValue;
|
||||
|
||||
js::DeflatedStringCache *deflatedStringCache;
|
||||
|
||||
JSString *emptyString;
|
||||
|
||||
/* List of active contexts sharing this runtime; protected by gcLock. */
|
||||
|
@ -2203,12 +2203,6 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
|
||||
}
|
||||
TIMESTAMP(sweepObjectEnd);
|
||||
|
||||
/*
|
||||
* We sweep the deflated cache before we finalize the strings so the
|
||||
* cache can safely use js_IsAboutToBeFinalized..
|
||||
*/
|
||||
rt->deflatedStringCache->sweep(cx);
|
||||
|
||||
for (JSCompartment **comp = rt->compartments.begin(); comp != rt->compartments.end(); comp++) {
|
||||
FinalizeArenaList<JSShortString>(*comp, cx, FINALIZE_SHORT_STRING);
|
||||
FinalizeArenaList<JSString>(*comp, cx, FINALIZE_STRING);
|
||||
|
@ -82,7 +82,7 @@ Probes::FunctionLineNumber(JSContext *cx, const JSFunction *fun)
|
||||
*
|
||||
* jsval returned
|
||||
* -------------------
|
||||
* STRING -> char *
|
||||
* STRING -> void *
|
||||
* INT -> int
|
||||
* DOUBLE -> double *
|
||||
* BOOLEAN -> int
|
||||
@ -109,9 +109,6 @@ jsprobes_jsvaltovoid(JSContext *cx, const js::Value &argval)
|
||||
if (argval.isBoolean())
|
||||
return (void *)argval.toBoolean();
|
||||
|
||||
if (argval.isString())
|
||||
return (void *)js_GetStringBytes(cx, argval.toString());
|
||||
|
||||
if (argval.isNumber()) {
|
||||
if (argval.isInt32())
|
||||
return (void *)argval.toInt32();
|
||||
|
@ -164,8 +164,6 @@ template <class T,
|
||||
class AllocPolicy = ContextAllocPolicy>
|
||||
class HashSet;
|
||||
|
||||
class DeflatedStringCache;
|
||||
|
||||
class PropertyCache;
|
||||
struct PropertyCacheEntry;
|
||||
|
||||
|
178
js/src/jsstr.cpp
178
js/src/jsstr.cpp
@ -3294,12 +3294,6 @@ __attribute__ ((aligned (8)))
|
||||
|
||||
#undef R
|
||||
|
||||
#define R(c) FROM_SMALL_CHAR((c) >> 6), FROM_SMALL_CHAR((c) & 0x3f), 0x00
|
||||
|
||||
const char JSString::deflatedLength2StringTable[] = { R12(0) };
|
||||
|
||||
#undef R
|
||||
|
||||
/*
|
||||
* Declare int strings. Only int strings from 100 to 255 actually have to be
|
||||
* generated, since the rest are either unit strings or length-2 strings. To
|
||||
@ -3350,16 +3344,6 @@ const JSString *const JSString::intStringTable[] = { R8(0) };
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#define R(c) ((c) / 100) + '0', ((c) / 10 % 10) + '0', ((c) % 10) + '0', 0x00
|
||||
|
||||
const char JSString::deflatedIntStringTable[] = {
|
||||
R7(100), /* 100 through 227 */
|
||||
R4(100 + (1 << 7)), /* 228 through 243 */
|
||||
R3(100 + (1 << 7) + (1 << 4)), /* 244 through 251 */
|
||||
R2(100 + (1 << 7) + (1 << 4) + (1 << 3)) /* 252 through 255 */
|
||||
};
|
||||
|
||||
#undef R
|
||||
#undef R2
|
||||
#undef R4
|
||||
#undef R6
|
||||
@ -3370,18 +3354,6 @@ const char JSString::deflatedIntStringTable[] = {
|
||||
#undef R3
|
||||
#undef R7
|
||||
|
||||
/* Static table for common UTF8 encoding */
|
||||
#define U8(c) char(((c) >> 6) | 0xc0), char(((c) & 0x3f) | 0x80), 0
|
||||
#define U(c) U8(c), U8(c+1), U8(c+2), U8(c+3), U8(c+4), U8(c+5), U8(c+6), U8(c+7)
|
||||
|
||||
const char JSString::deflatedUnitStringTable[] = {
|
||||
U(0x80), U(0x88), U(0x90), U(0x98), U(0xa0), U(0xa8), U(0xb0), U(0xb8),
|
||||
U(0xc0), U(0xc8), U(0xd0), U(0xd8), U(0xe0), U(0xe8), U(0xf0), U(0xf8)
|
||||
};
|
||||
|
||||
#undef U
|
||||
#undef U8
|
||||
|
||||
JSBool
|
||||
js_String(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
@ -4012,7 +3984,7 @@ js_InflateString(JSContext *cx, const char *bytes, size_t *lengthp)
|
||||
}
|
||||
|
||||
/*
|
||||
* May be called with null cx by js_GetStringBytes, see below.
|
||||
* May be called with null cx.
|
||||
*/
|
||||
char *
|
||||
js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
|
||||
@ -4057,7 +4029,7 @@ js_GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
||||
}
|
||||
|
||||
/*
|
||||
* May be called with null cx through js_GetStringBytes, see below.
|
||||
* May be called with null cx through public API, see below.
|
||||
*/
|
||||
size_t
|
||||
js_GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
||||
@ -4300,152 +4272,6 @@ bufferTooSmall:
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
DeflatedStringCache::DeflatedStringCache()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
lock = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
DeflatedStringCache::init()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ASSERT(!lock);
|
||||
lock = JS_NEW_LOCK();
|
||||
if (!lock)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make room for 2K deflated strings that a typical browser session
|
||||
* creates.
|
||||
*/
|
||||
return map.init(2048);
|
||||
}
|
||||
|
||||
DeflatedStringCache::~DeflatedStringCache()
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
if (lock)
|
||||
JS_DESTROY_LOCK(lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DeflatedStringCache::sweep(JSContext *cx)
|
||||
{
|
||||
/*
|
||||
* We must take a lock even during the GC as JS_GetFunctionName can be
|
||||
* called outside the request.
|
||||
*/
|
||||
JS_ACQUIRE_LOCK(lock);
|
||||
|
||||
for (Map::Enum e(map); !e.empty(); e.popFront()) {
|
||||
JSString *str = e.front().key;
|
||||
if (IsAboutToBeFinalized(str)) {
|
||||
char *bytes = e.front().value;
|
||||
e.removeFront();
|
||||
|
||||
/*
|
||||
* We cannot use cx->free here as bytes may come from the
|
||||
* embedding that calls JS_NewString(cx, bytes, length). Those
|
||||
* bytes may not be allocated via js_malloc and may not have
|
||||
* space for the background free list.
|
||||
*/
|
||||
js_free(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
JS_RELEASE_LOCK(lock);
|
||||
}
|
||||
|
||||
char *
|
||||
DeflatedStringCache::getBytes(JSString *str)
|
||||
{
|
||||
JS_ACQUIRE_LOCK(lock);
|
||||
Map::AddPtr p = map.lookupForAdd(str);
|
||||
char *bytes = p ? p->value : NULL;
|
||||
JS_RELEASE_LOCK(lock);
|
||||
|
||||
if (bytes)
|
||||
return bytes;
|
||||
|
||||
bytes = js_DeflateString(NULL, str->chars(), str->length());
|
||||
if (!bytes)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* In the single-threaded case we use the add method as js_DeflateString
|
||||
* cannot mutate the map. In particular, it cannot run the GC that may
|
||||
* delete entries from the map. But the JS_THREADSAFE version requires to
|
||||
* deal with other threads adding the entries to the map.
|
||||
*/
|
||||
char *bytesToFree = NULL;
|
||||
JSBool ok;
|
||||
#ifdef JS_THREADSAFE
|
||||
JS_ACQUIRE_LOCK(lock);
|
||||
ok = map.relookupOrAdd(p, str, bytes);
|
||||
if (ok && p->value != bytes) {
|
||||
/* Some other thread has asked for str bytes .*/
|
||||
JS_ASSERT(!strcmp(p->value, bytes));
|
||||
bytesToFree = bytes;
|
||||
bytes = p->value;
|
||||
}
|
||||
JS_RELEASE_LOCK(lock);
|
||||
#else /* !JS_THREADSAFE */
|
||||
ok = map.add(p, str, bytes);
|
||||
#endif
|
||||
if (!ok) {
|
||||
bytesToFree = bytes;
|
||||
bytes = NULL;
|
||||
}
|
||||
|
||||
if (bytesToFree)
|
||||
js_free(bytesToFree);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
const char *
|
||||
js_GetStringBytes(JSAtom *atom)
|
||||
{
|
||||
JSString *str = ATOM_TO_STRING(atom);
|
||||
if (JSString::isUnitString(str)) {
|
||||
char *bytes;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
/* Unit string data is {c, 0, 0, 0} so we can just cast. */
|
||||
bytes = (char *)str->chars();
|
||||
#else
|
||||
/* Unit string data is {0, c, 0, 0} so we can point into the middle. */
|
||||
bytes = (char *)str->chars() + 1;
|
||||
#endif
|
||||
return ((*bytes & 0x80) && js_CStringsAreUTF8)
|
||||
? JSString::deflatedUnitStringTable + ((*bytes & 0x7f) * 3)
|
||||
: bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must burn some space on deflated int strings and length-2 strings
|
||||
* to preserve static allocation (which is to say, JSRuntime independence).
|
||||
*/
|
||||
if (JSString::isLength2String(str))
|
||||
return JSString::deflatedLength2StringTable + ((str - JSString::length2StringTable) * 3);
|
||||
|
||||
if (JSString::isHundredString(str)) {
|
||||
/*
|
||||
* We handled the 1 and 2-digit number cases already, so we know that
|
||||
* str is between 100 and 255.
|
||||
*/
|
||||
return JSString::deflatedIntStringTable + ((str - JSString::hundredStringTable) * 4);
|
||||
}
|
||||
|
||||
return GetGCThingRuntime(str)->deflatedStringCache->getBytes(str);
|
||||
}
|
||||
|
||||
/*
|
||||
* From java.lang.Character.java:
|
||||
*
|
||||
|
@ -514,9 +514,6 @@ struct JSString {
|
||||
* strings, we keep a table to map from integer to the correct string.
|
||||
*/
|
||||
static const JSString *const intStringTable[];
|
||||
static const char deflatedIntStringTable[];
|
||||
static const char deflatedUnitStringTable[];
|
||||
static const char deflatedLength2StringTable[];
|
||||
|
||||
static JSString *unitString(jschar c);
|
||||
static JSString *getUnitString(JSContext *cx, JSString *str, size_t index);
|
||||
@ -1146,13 +1143,6 @@ extern JSBool
|
||||
js_DeflateStringToUTF8Buffer(JSContext *cx, const jschar *chars,
|
||||
size_t charsLength, char *bytes, size_t *length);
|
||||
|
||||
/*
|
||||
* Find or create a deflated string cache entry for str that contains its
|
||||
* characters chopped from Unicode code points into bytes.
|
||||
*/
|
||||
extern const char *
|
||||
js_GetStringBytes(JSAtom *atom);
|
||||
|
||||
/* Export a few natives and a helper to other files in SpiderMonkey. */
|
||||
extern JSBool
|
||||
js_str_escape(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
|
||||
@ -1223,54 +1213,4 @@ FileEscapedString(FILE *fp, JSString *str, uint32 quote)
|
||||
extern JSBool
|
||||
js_String(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
namespace js {
|
||||
|
||||
class DeflatedStringCache {
|
||||
public:
|
||||
DeflatedStringCache();
|
||||
bool init();
|
||||
~DeflatedStringCache();
|
||||
|
||||
void sweep(JSContext *cx);
|
||||
|
||||
private:
|
||||
struct StringPtrHasher
|
||||
{
|
||||
typedef JSString *Lookup;
|
||||
|
||||
static HashNumber hash(JSString *str) {
|
||||
/*
|
||||
* We hash only GC-allocated Strings. They are aligned on
|
||||
* sizeof(JSString) boundary so we can improve hashing by stripping
|
||||
* initial zeros.
|
||||
*/
|
||||
const jsuword ALIGN_LOG = tl::FloorLog2<sizeof(JSString)>::result;
|
||||
JS_STATIC_ASSERT(sizeof(JSString) == (size_t(1) << ALIGN_LOG));
|
||||
|
||||
jsuword ptr = reinterpret_cast<jsuword>(str);
|
||||
jsuword key = ptr >> ALIGN_LOG;
|
||||
JS_ASSERT((key << ALIGN_LOG) == ptr);
|
||||
return HashNumber(key);
|
||||
}
|
||||
|
||||
static bool match(JSString *s1, JSString *s2) {
|
||||
return s1 == s2;
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashMap<JSString *, char *, StringPtrHasher, SystemAllocPolicy> Map;
|
||||
|
||||
char *getBytes(JSString *str);
|
||||
|
||||
friend const char *
|
||||
::js_GetStringBytes(JSAtom *atom);
|
||||
|
||||
Map map;
|
||||
#ifdef JS_THREADSAFE
|
||||
JSLock *lock;
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsstr_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user