diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index cd86792aa7a..ebe28c5ced1 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4880,7 +4880,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) } /* Make the function object a literal in the outer script's pool. */ - unsigned index = bce->objectList.add(pn->pn_funbox); + unsigned index = bce->objectList.add(&pn->pn_funbox->objbox); /* Non-hoisted functions simply emit their respective op. */ if (!pn->functionIsHoisted()) { diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 9111ada7a5c..623ed371f42 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -445,7 +445,7 @@ CloneParseTree(ParseNode *opn, Parser *parser) case PN_FUNC: NULLCHECK(pn->pn_funbox = - parser->newFunctionBox(opn->pn_funbox->object, pc, opn->pn_funbox->strictModeState)); + parser->newFunctionBox(opn->pn_funbox->fun(), pc, opn->pn_funbox->strictModeState)); NULLCHECK(pn->pn_body = CloneParseTree(opn->pn_body, parser)); pn->pn_cookie = opn->pn_cookie; pn->pn_dflags = opn->pn_dflags; diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 70a3408c72b..c3fb31dda75 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -1465,9 +1465,14 @@ struct ObjectBox { ObjectBox *traceLink; ObjectBox *emitLink; JSObject *object; - bool isFunctionBox; + + // An ObjectBox can hold a JSObject or a JSFunction. In the latter case, + // the ObjectBox will be embedded within a FunctionBox; |funbox| points to + // that FunctionBox. + FunctionBox *const funbox; ObjectBox(ObjectBox *traceLink, JSObject *obj); + ObjectBox(ObjectBox *traceLink, JSFunction *fun, FunctionBox *funbox); }; } /* namespace frontend */ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 1fba743eb76..9082a320a6b 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -362,7 +362,15 @@ ObjectBox::ObjectBox(ObjectBox* traceLink, JSObject *obj) : traceLink(traceLink), emitLink(NULL), object(obj), - isFunctionBox(false) + funbox(NULL) +{ +} + +ObjectBox::ObjectBox(ObjectBox* traceLink, JSFunction *fun, FunctionBox *funbox) + : traceLink(traceLink), + emitLink(NULL), + object(fun), + funbox(funbox) { } @@ -390,9 +398,9 @@ Parser::newObjectBox(JSObject *obj) return objbox; } -FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseContext *outerpc, +FunctionBox::FunctionBox(ObjectBox *traceListHead, JSFunction *fun, ParseContext *outerpc, StrictMode sms) - : ObjectBox(traceListHead, obj), + : objbox(traceListHead, fun, this), siblings(outerpc ? outerpc->functionList : NULL), kids(NULL), bindings(), @@ -404,8 +412,6 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseContext * inGenexpLambda(false), cxFlags() // the cxFlags are set in LeaveFunction { - isFunctionBox = true; - if (!outerpc) { inWith = false; @@ -450,10 +456,9 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseContext * } FunctionBox * -Parser::newFunctionBox(JSObject *obj, ParseContext *outerpc, StrictMode sms) +Parser::newFunctionBox(JSFunction *fun, ParseContext *outerpc, StrictMode sms) { - JS_ASSERT(obj && !IsPoisonedPtr(obj)); - JS_ASSERT(obj->isFunction()); + JS_ASSERT(fun && !IsPoisonedPtr(fun)); /* * We use JSContext.tempLifoAlloc to allocate parsed objects and place them @@ -463,7 +468,7 @@ Parser::newFunctionBox(JSObject *obj, ParseContext *outerpc, StrictMode sms) * function. */ FunctionBox *funbox = - context->tempLifoAlloc().new_(traceListHead, obj, outerpc, sms); + context->tempLifoAlloc().new_(traceListHead, fun, outerpc, sms); if (!funbox) { js_ReportOutOfMemory(context); return NULL; @@ -471,7 +476,7 @@ Parser::newFunctionBox(JSObject *obj, ParseContext *outerpc, StrictMode sms) if (outerpc) outerpc->functionList = funbox; - traceListHead = funbox; + traceListHead = &funbox->objbox; return funbox; } @@ -482,8 +487,8 @@ Parser::trace(JSTracer *trc) ObjectBox *objbox = traceListHead; while (objbox) { MarkObjectRoot(trc, &objbox->object, "parser.object"); - if (objbox->isFunctionBox) - static_cast(objbox)->bindings.trace(trc); + if (objbox->funbox) + objbox->funbox->bindings.trace(trc); objbox = objbox->traceLink; } } diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index e1c81fc4d7c..ee52d00bdef 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -303,7 +303,7 @@ struct Parser : private AutoGCRooter */ ObjectBox *newObjectBox(JSObject *obj); - FunctionBox *newFunctionBox(JSObject *obj, ParseContext *pc, StrictMode sms); + FunctionBox *newFunctionBox(JSFunction *fun, ParseContext *pc, StrictMode sms); /* * Create a new function object given parse context (pc) and a name (which diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 4ecad995784..a437828d00c 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -283,8 +283,9 @@ struct StmtInfoBase { } }; -struct FunctionBox : public ObjectBox +struct FunctionBox { + ObjectBox objbox; FunctionBox *siblings; FunctionBox *kids; Bindings bindings; /* bindings for this function */ @@ -298,12 +299,11 @@ struct FunctionBox : public ObjectBox ContextFlags cxFlags; - FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseContext *pc, - StrictMode sms); + FunctionBox(ObjectBox *traceListHead, JSFunction *fun, ParseContext *pc, StrictMode sms); bool funIsGenerator() const { return cxFlags.funIsGenerator; } - JSFunction *fun() const { return (JSFunction *) object; } + JSFunction *fun() const { return objbox.object->toFunction(); } void recursivelySetStrictMode(StrictMode strictness); }; diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index bbfcb95cf39..7e661dd1c9b 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -3100,7 +3100,7 @@ ASTSerializer::identifier(ParseNode *pn, Value *dst) bool ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst) { - JSFunction *func = (JSFunction *)pn->pn_funbox->object; + JSFunction *func = pn->pn_funbox->fun(); bool isGenerator = #if JS_HAS_GENERATORS