From 9c36d75cba9f74a6333a29e9d0b8e341fe3cad6c Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Wed, 13 Jul 2011 02:34:40 +0200 Subject: [PATCH 01/15] Bug 666452 - Part 1: Expose functions to get the (stroked) bounds of a path. r=BenWa sr=roc --- gfx/2d/2D.h | 14 ++++++++++++++ gfx/2d/DrawTargetD2D.h | 2 +- gfx/2d/PathD2D.cpp | 37 ++++++++++++++++++++++++++++++++++++- gfx/2d/PathD2D.h | 5 +++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 49f7d81bf744..bb6617c8efc9 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -380,6 +380,20 @@ public: */ virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const = 0; + /* This functions gets the bounds of this path. These bounds are not + * guaranteed to be tight. A transform may be specified that gives the bounds + * after application of the transform. + */ + virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const = 0; + + /* This function gets the bounds of the stroke of this path using the + * specified strokeoptions. These bounds are not guaranteed to be tight. + * A transform may be specified that gives the bounds after application of + * the transform. + */ + virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, + const Matrix &aTransform = Matrix()) const = 0; + /* This gets the fillrule this path's builder was created with. This is not * mutable. */ diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index 8b8e941706df..08fa355ad3d4 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -137,6 +137,7 @@ public: bool InitD3D10Data(); static ID2D1Factory *factory(); + static TemporaryRef CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions); operator std::string() const { std::stringstream stream; @@ -163,7 +164,6 @@ private: TemporaryRef GetClippedGeometry(); TemporaryRef CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); - TemporaryRef CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions); TemporaryRef CreateGradientTexture(const GradientStopsD2D *aStops); diff --git a/gfx/2d/PathD2D.cpp b/gfx/2d/PathD2D.cpp index 34c9f3e825db..440e3c59cb70 100644 --- a/gfx/2d/PathD2D.cpp +++ b/gfx/2d/PathD2D.cpp @@ -344,5 +344,40 @@ PathD2D::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const return !!result; } +Rect +PathD2D::GetBounds(const Matrix &aTransform) const +{ + D2D1_RECT_F bounds; + + HRESULT hr = mGeometry->GetBounds(D2DMatrix(aTransform), &bounds); + + if (FAILED(hr)) { + gfxWarning() << "Failed to get stroked bounds for path. Code: " << hr; + bounds.bottom = bounds.left = bounds.right = bounds.top = 0; + } + + return ToRect(bounds); +} + +Rect +PathD2D::GetStrokedBounds(const StrokeOptions &aStrokeOptions, + const Matrix &aTransform) const +{ + D2D1_RECT_F bounds; + + RefPtr strokeStyle = + DrawTargetD2D::CreateStrokeStyleForOptions(aStrokeOptions); + HRESULT hr = + mGeometry->GetWidenedBounds(aStrokeOptions.mLineWidth, strokeStyle, + D2DMatrix(aTransform), &bounds); + + if (FAILED(hr)) { + gfxWarning() << "Failed to get stroked bounds for path. Code: " << hr; + bounds.bottom = bounds.left = bounds.right = bounds.top = 0; + } + + return ToRect(bounds); +} + +} } -} \ No newline at end of file diff --git a/gfx/2d/PathD2D.h b/gfx/2d/PathD2D.h index cb3d90d8227f..f759902cf967 100644 --- a/gfx/2d/PathD2D.h +++ b/gfx/2d/PathD2D.h @@ -107,6 +107,11 @@ public: virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const; + virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const; + + virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions, + const Matrix &aTransform = Matrix()) const; + virtual FillRule GetFillRule() const { return mFillRule; } ID2D1Geometry *GetGeometry() { return mGeometry; } From e72bf56f2212a10691eaaba20c306c3e50ce9c65 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Wed, 13 Jul 2011 02:34:43 +0200 Subject: [PATCH 02/15] Bug 666452 - Part 2: Minimize drawing done with shadow in the Azure D2D backend. r=BenWa --- gfx/2d/DrawTargetD2D.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 0ca96bc879d9..22684bf9bffc 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -295,6 +295,9 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, return; } + // XXX - This function is way too long, it should be split up soon to make + // it more graspable! + Flush(); AutoSaveRestoreClippedOut restoreClippedOut(this); @@ -325,6 +328,9 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, RefPtr maskTexture; RefPtr maskSRView; if (mPushedClips.size()) { + // Here we render a mask of the clipped out area for use as an input to the + // shadow drawing. + CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_A8_UNORM, mSize.width, mSize.height, 1, 1); @@ -579,15 +585,23 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, rtViews = destRTView; mDevice->OMSetRenderTargets(1, &rtViews, NULL); + Point shadowDest = aDest + aOffset; + + mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> + SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((shadowDest.x / mSize.width) * 2.0f), + 1.0f - (shadowDest.y / mSize.height * 2.0f), + (Float(aSurface->GetSize().width) / mSize.width) * 2.0f, + (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f)); mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-correctedOffset.x / Float(tmpSurfSize.width), -correctedOffset.y / Float(tmpSurfSize.height), - mSize.width / Float(tmpSurfSize.width) * dsFactorX, - mSize.height / Float(tmpSurfSize.height) * dsFactorY)); + SetFloatVector(ShaderConstantRectD3D10(0, 0, Float(srcSurfSize.width) / tmpSurfSize.width, + Float(srcSurfSize.height) / tmpSurfSize.height)); if (mPushedClips.size()) { mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView); mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); + SetFloatVector(ShaderConstantRectD3D10(shadowDest.x / mSize.width, shadowDest.y / mSize.width, + Float(aSurface->GetSize().width) / mSize.width, + Float(aSurface->GetSize().height) / mSize.height)); mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")-> GetPassByIndex(2)->Apply(0); } else { @@ -599,12 +613,20 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, mDevice->Draw(4, 0); + mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()-> + SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((aDest.x / mSize.width) * 2.0f), + 1.0f - (aDest.y / mSize.height * 2.0f), + (Float(aSurface->GetSize().width) / mSize.width) * 2.0f, + (-Float(aSurface->GetSize().height) / mSize.height) * 2.0f)); mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(static_cast(aSurface)->GetSRView()); mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()-> - SetFloatVector(ShaderConstantRectD3D10(-aDest.x / aSurface->GetSize().width, -aDest.y / aSurface->GetSize().height, - Float(mSize.width) / aSurface->GetSize().width, - Float(mSize.height) / aSurface->GetSize().height)); + SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); + if (mPushedClips.size()) { + mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()-> + SetFloatVector(ShaderConstantRectD3D10(aDest.x / mSize.width, aDest.y / mSize.width, + Float(aSurface->GetSize().width) / mSize.width, + Float(aSurface->GetSize().height) / mSize.height)); mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")-> GetPassByIndex(0)->Apply(0); } else { From 8367a2ca668cdfbd604c0f8ded77e9c833139a0a Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Wed, 13 Jul 2011 02:36:28 +0200 Subject: [PATCH 03/15] Bug 666452 - Part 3: Create a minimal size temp surface for canvas shadow drawing. r=roc --- .../src/nsCanvasRenderingContext2DAzure.cpp | 136 +++++++++++------- gfx/2d/2D.h | 4 +- 2 files changed, 88 insertions(+), 52 deletions(-) diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 2a5916954b33..0e83e026e937 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -826,12 +826,17 @@ protected: /* This is an RAII based class that can be used as a drawtarget for * operations that need a shadow drawn. It will automatically provide a * temporary target when needed, and if so blend it back with a shadow. + * + * aBounds specifies the bounds of the drawing operation that will be + * drawn to the target, it is given in device space! This function will + * change aBounds to incorporate shadow bounds. If this is NULL the drawing + * operation will be assumed to cover an infinite rect. */ class AdjustedTarget { public: AdjustedTarget(nsCanvasRenderingContext2DAzure *ctx, - const mgfx::Rect *aBounds = nsnull) + mgfx::Rect *aBounds = nsnull) : mCtx(nsnull) { if (!ctx->NeedToDrawShadow()) { @@ -849,48 +854,43 @@ protected: } Matrix transform = mCtx->mTarget->GetTransform(); - if (!aBounds) { - mTempSize = IntSize(ctx->mWidth, ctx->mHeight); - // We need to enlarge an possibly offset our temporary surface - // so that things outside of the canvas may cast shadows. - if (state.shadowOffset.x > 0) { - mTempSize.width += state.shadowOffset.x; - mSurfOffset.x = -state.shadowOffset.x; - transform._31 += state.shadowOffset.x; - } else { - mTempSize.width -= state.shadowOffset.x; - } - if (state.shadowOffset.y > 0) { - mTempSize.height += state.shadowOffset.y; - mSurfOffset.y = -state.shadowOffset.y; - transform._32 += state.shadowOffset.y; - } else { - mTempSize.height -= state.shadowOffset.y; - } + mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight); - if (mSigma > 0) { - float blurRadius = mSigma * 3; - mSurfOffset.x -= blurRadius; - mSurfOffset.y -= blurRadius; - mTempSize.width += blurRadius; - mTempSize.height += blurRadius; - transform._31 += blurRadius; - transform._32 += blurRadius; - } - } // XXX - Implement aBounds path! See bug 666452. + Float blurRadius = mSigma * 3; + + // We need to enlarge and possibly offset our temporary surface + // so that things outside of the canvas may cast shadows. + mTempRect.Inflate(Margin(blurRadius + NS_MAX(state.shadowOffset.x, 0), + blurRadius + NS_MAX(state.shadowOffset.y, 0), + blurRadius + NS_MAX(-state.shadowOffset.x, 0), + blurRadius + NS_MAX(-state.shadowOffset.y, 0))); + + if (aBounds) { + // We actually include the bounds of the shadow blur, this makes it + // easier to execute the actual blur on hardware, and shouldn't affect + // the amount of pixels that need to be touched. + aBounds->Inflate(Margin(blurRadius, blurRadius, + blurRadius, blurRadius)); + mTempRect = mTempRect.Intersect(*aBounds); + } + + mTempRect.ScaleRoundOut(1.0f); + + transform._31 -= mTempRect.x; + transform._32 -= mTempRect.y; mTarget = - mCtx->mTarget->CreateSimilarDrawTarget(mTempSize, - FORMAT_B8G8R8A8); - - mTarget->SetTransform(transform); + mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), + FORMAT_B8G8R8A8); if (!mTarget) { // XXX - Deal with the situation where our temp size is too big to // fit in a texture. mTarget = ctx->mTarget; mCtx = nsnull; + } else { + mTarget->SetTransform(transform); } } @@ -902,7 +902,7 @@ protected: RefPtr snapshot = mTarget->Snapshot(); - mCtx->mTarget->DrawSurfaceWithShadow(snapshot, mSurfOffset, + mCtx->mTarget->DrawSurfaceWithShadow(snapshot, mTempRect.TopLeft(), Color::FromABGR(mCtx->CurrentState().shadowColor), mCtx->CurrentState().shadowOffset, mSigma, mCtx->CurrentState().op); @@ -917,8 +917,7 @@ protected: RefPtr mTarget; nsCanvasRenderingContext2DAzure *mCtx; Float mSigma; - IntSize mTempSize; - Point mSurfOffset; + mgfx::Rect mTempRect; }; nsAutoTArray mStyleStack; @@ -2113,9 +2112,17 @@ nsCanvasRenderingContext2DAzure::FillRect(float x, float y, float w, float h) } } - AdjustedTarget(this)->FillRect(mgfx::Rect(x, y, w, h), - GeneralPattern().ForStyle(this, STYLE_FILL, mTarget), - DrawOptions(state.globalAlpha, UsedOperation())); + mgfx::Rect bounds; + + if (NeedToDrawShadow()) { + bounds = mgfx::Rect(x, y, w, h); + bounds = mTarget->GetTransform().TransformBounds(bounds); + } + + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> + FillRect(mgfx::Rect(x, y, w, h), + GeneralPattern().ForStyle(this, STYLE_FILL, mTarget), + DrawOptions(state.globalAlpha, UsedOperation())); return RedrawUser(gfxRect(x, y, w, h)); } @@ -2129,6 +2136,14 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) const ContextState &state = CurrentState(); + mgfx::Rect bounds; + + if (NeedToDrawShadow()) { + bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f, + w + state.lineWidth, h + state.lineWidth); + bounds = mTarget->GetTransform().TransformBounds(bounds); + } + if (!w && !h) { return NS_OK; } else if (!h) { @@ -2136,7 +2151,7 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) if (state.lineJoin == JOIN_ROUND) { cap = CAP_ROUND; } - AdjustedTarget(this)-> + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> StrokeLine(Point(x, y), Point(x + w, y), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, @@ -2151,7 +2166,7 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) if (state.lineJoin == JOIN_ROUND) { cap = CAP_ROUND; } - AdjustedTarget(this)-> + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> StrokeLine(Point(x, y), Point(x, y + h), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, @@ -2163,7 +2178,7 @@ nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h) return NS_OK; } - AdjustedTarget(this)-> + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> StrokeRect(mgfx::Rect(x, y, w, h), GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), StrokeOptions(state.lineWidth, state.lineJoin, @@ -2213,7 +2228,13 @@ nsCanvasRenderingContext2DAzure::Fill() return NS_OK; } - AdjustedTarget(this)-> + mgfx::Rect bounds; + + if (NeedToDrawShadow()) { + bounds = mPath->GetBounds(mTarget->GetTransform()); + } + + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> Fill(mPath, GeneralPattern().ForStyle(this, STYLE_FILL, mTarget), DrawOptions(CurrentState().globalAlpha, UsedOperation())); @@ -2231,14 +2252,20 @@ nsCanvasRenderingContext2DAzure::Stroke() const ContextState &state = CurrentState(); - AdjustedTarget(this)-> + StrokeOptions strokeOptions(state.lineWidth, state.lineJoin, + state.lineCap, state.miterLimit, + state.dash.Length(), state.dash.Elements(), + state.dashOffset); + + mgfx::Rect bounds; + if (NeedToDrawShadow()) { + bounds = + mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform()); + } + + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> Stroke(mPath, GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget), - StrokeOptions(state.lineWidth, state.lineJoin, - state.lineCap, state.miterLimit, - state.dash.Length(), - state.dash.Elements(), - state.dashOffset), - DrawOptions(state.globalAlpha, UsedOperation())); + strokeOptions, DrawOptions(state.globalAlpha, UsedOperation())); return Redraw(); } @@ -3758,7 +3785,14 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1, else filter = mgfx::FILTER_POINT; - AdjustedTarget(this)-> + mgfx::Rect bounds; + + if (NeedToDrawShadow()) { + bounds = mgfx::Rect(dx, dy, dw, dh); + bounds = mTarget->GetTransform().TransformBounds(bounds); + } + + AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)-> DrawSurface(srcSurf, mgfx::Rect(dx, dy, dw, dh), mgfx::Rect(sx, sy, sw, sh), diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index bb6617c8efc9..bacec3496e50 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -492,7 +492,9 @@ public: /* * Blend a surface to the draw target with a shadow. The shadow is drawn as a - * gaussian blur using a specified sigma. + * gaussian blur using a specified sigma. The shadow is clipped to the size + * of the input surface, so the input surface should contain a transparent + * border the size of the approximate coverage of the blur (3 * aSigma). * NOTE: This function works in device space! * * aSurface Source surface to draw. From e6bd9fa6a0ef1c8b073d0209a9f468572514832c Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Wed, 13 Jul 2011 08:56:39 +0100 Subject: [PATCH 04/15] Bug 664130. Remove redundant isPositioned check. r=roc. --- layout/generic/nsFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 17223acdbded..7291fd3d10eb 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1741,7 +1741,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } if (NS_SUCCEEDED(rv)) { - if (isPositioned && applyAbsPosClipping) { + if (applyAbsPosClipping) { nsAbsPosClipWrapper wrapper(clipRect); rv = wrapper.WrapListsInPlace(aBuilder, aChild, pseudoStack); } From dd807c3d303b871c32ac10e44d18d4ba5c8e7bd9 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Wed, 13 Jul 2011 07:15:59 -0500 Subject: [PATCH 05/15] Bug 620316 - Remove WrapEscapingClosure. r=brendan. --- js/src/jsfun.cpp | 250 +------------------------------------------- js/src/jsfun.h | 11 -- js/src/jsinterp.cpp | 81 +------------- js/src/jsopcode.cpp | 4 - js/src/jsopcode.tbl | 27 ++--- js/src/jstracer.cpp | 27 +---- js/src/jsxdrapi.h | 2 +- 7 files changed, 18 insertions(+), 384 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 4d35e3218cab..ce6044b8cf73 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -361,160 +361,6 @@ args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) return true; } -static JS_REQUIRES_STACK JSObject * -WrapEscapingClosure(JSContext *cx, StackFrame *fp, JSFunction *fun) -{ - JS_ASSERT(fun->optimizedClosure()); - JS_ASSERT(!fun->u.i.wrapper); - - /* - * We do not attempt to reify Call and Block objects on demand for outer - * scopes. This could be done (see the "v8" patch in bug 494235) but it is - * fragile in the face of ongoing compile-time optimization. Instead, the - * _DBG* opcodes used by wrappers created here must cope with unresolved - * upvars and throw them as reference errors. Caveat debuggers! - */ - JSObject *scopeChain = GetScopeChain(cx, fp); - if (!scopeChain) - return NULL; - - JSObject *wfunobj = NewFunction(cx, scopeChain); - if (!wfunobj) - return NULL; - AutoObjectRooter tvr(cx, wfunobj); - - JSFunction *wfun = (JSFunction *) wfunobj; - wfunobj->setPrivate(wfun); - wfun->nargs = fun->nargs; - wfun->flags = fun->flags | JSFUN_HEAVYWEIGHT; - wfun->u.i.skipmin = fun->u.i.skipmin; - wfun->u.i.wrapper = true; - wfun->u.i.script = NULL; - wfun->atom = fun->atom; - - JSScript *script = fun->script(); - jssrcnote *snbase = script->notes(); - jssrcnote *sn = snbase; - while (!SN_IS_TERMINATOR(sn)) - sn = SN_NEXT(sn); - uintN nsrcnotes = (sn - snbase) + 1; - - /* NB: GC must not occur before wscript is homed in wfun->u.i.script. */ - JSScript *wscript = JSScript::NewScript(cx, script->length, nsrcnotes, - script->atomMap.length, - JSScript::isValidOffset(script->objectsOffset) - ? script->objects()->length - : 0, - script->bindings.countUpvars(), - JSScript::isValidOffset(script->regexpsOffset) - ? script->regexps()->length - : 0, - JSScript::isValidOffset(script->trynotesOffset) - ? script->trynotes()->length - : 0, - JSScript::isValidOffset(script->constOffset) - ? script->consts()->length - : 0, - JSScript::isValidOffset(script->globalsOffset) - ? script->globals()->length - : 0, - script->nClosedArgs, - script->nClosedVars, - script->getVersion()); - if (!wscript) - return NULL; - - memcpy(wscript->code, script->code, script->length); - wscript->main = wscript->code + (script->main - script->code); - - memcpy(wscript->notes(), snbase, nsrcnotes * sizeof(jssrcnote)); - memcpy(wscript->atomMap.vector, script->atomMap.vector, - wscript->atomMap.length * sizeof(JSAtom *)); - if (JSScript::isValidOffset(script->objectsOffset)) { - memcpy(wscript->objects()->vector, script->objects()->vector, - wscript->objects()->length * sizeof(JSObject *)); - } - if (JSScript::isValidOffset(script->regexpsOffset)) { - memcpy(wscript->regexps()->vector, script->regexps()->vector, - wscript->regexps()->length * sizeof(JSObject *)); - } - if (JSScript::isValidOffset(script->trynotesOffset)) { - memcpy(wscript->trynotes()->vector, script->trynotes()->vector, - wscript->trynotes()->length * sizeof(JSTryNote)); - } - if (JSScript::isValidOffset(script->globalsOffset)) { - memcpy(wscript->globals()->vector, script->globals()->vector, - wscript->globals()->length * sizeof(GlobalSlotArray::Entry)); - } - if (script->nClosedArgs + script->nClosedVars != 0) - script->copyClosedSlotsTo(wscript); - - if (script->bindings.hasUpvars()) { - JS_ASSERT(script->bindings.countUpvars() == wscript->upvars()->length); - memcpy(wscript->upvars()->vector, script->upvars()->vector, - script->bindings.countUpvars() * sizeof(uint32)); - } - - jsbytecode *pc = wscript->code; - while (*pc != JSOP_STOP) { - /* FIXME should copy JSOP_TRAP? */ - JSOp op = js_GetOpcode(cx, wscript, pc); - const JSCodeSpec *cs = &js_CodeSpec[op]; - ptrdiff_t oplen = cs->length; - if (oplen < 0) - oplen = js_GetVariableBytecodeLength(pc); - - /* - * Rewrite JSOP_{GET,CALL}FCSLOT as JSOP_{GET,CALL}UPVAR_DBG for the - * case where fun is an escaping flat closure. This works because the - * UPVAR and FCSLOT ops by design have the same format: an upvar index - * immediate operand. - */ - switch (op) { - case JSOP_GETFCSLOT: *pc = JSOP_GETUPVAR_DBG; break; - case JSOP_CALLFCSLOT: *pc = JSOP_CALLUPVAR_DBG; break; - case JSOP_DEFFUN_FC: *pc = JSOP_DEFFUN_DBGFC; break; - case JSOP_DEFLOCALFUN_FC: *pc = JSOP_DEFLOCALFUN_DBGFC; break; - case JSOP_LAMBDA_FC: *pc = JSOP_LAMBDA_DBGFC; break; - default:; - } - pc += oplen; - } - - /* - * Fill in the rest of wscript. This means if you add members to JSScript - * you must update this code. FIXME: factor into JSScript::clone method. - */ - JS_ASSERT(wscript->getVersion() == script->getVersion()); - wscript->nfixed = script->nfixed; - wscript->filename = script->filename; - wscript->lineno = script->lineno; - wscript->nslots = script->nslots; - wscript->staticLevel = script->staticLevel; - wscript->principals = script->principals; - wscript->noScriptRval = script->noScriptRval; - wscript->savedCallerFun = script->savedCallerFun; - wscript->hasSharps = script->hasSharps; - wscript->strictModeCode = script->strictModeCode; - wscript->compileAndGo = script->compileAndGo; - wscript->usesEval = script->usesEval; - wscript->usesArguments = script->usesArguments; - wscript->warnedAboutTwoArgumentEval = script->warnedAboutTwoArgumentEval; - if (wscript->principals) - JSPRINCIPALS_HOLD(cx, wscript->principals); -#ifdef CHECK_SCRIPT_OWNER - wscript->owner = script->owner; -#endif - - wscript->bindings.clone(cx, &script->bindings); - - /* Deoptimize wfun from FUN_{FLAT,NULL}_CLOSURE to FUN_INTERPRETED. */ - FUN_SET_KIND(wfun, JSFUN_INTERPRETED); - wfun->u.i.script = wscript; - js_CallNewScriptHook(cx, wscript, wfun); - return wfunobj; -} - static JSBool ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) { @@ -543,22 +389,8 @@ ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) } else { JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)); const Value &v = argsobj->callee(); - if (!v.isMagic(JS_ARGS_HOLE)) { - /* - * If this function or one in it needs upvars that reach above it - * in the scope chain, it must not be a null closure (it could be a - * flat closure, or an unoptimized closure -- the latter itself not - * necessarily heavyweight). Rather than wrap here, we simply throw - * to reduce code size and tell debugger users the truth instead of - * passing off a fibbing wrapper. - */ - if (GET_FUNCTION_PRIVATE(cx, &v.toObject())->needsWrapper()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_OPTIMIZED_CLOSURE_LEAK); - return false; - } + if (!v.isMagic(JS_ARGS_HOLE)) *vp = v; - } } return true; } @@ -915,49 +747,6 @@ Class js_DeclEnvClass = { ConvertStub }; -static JSBool -CheckForEscapingClosure(JSContext *cx, JSObject *obj, Value *vp) -{ - JS_ASSERT(obj->isCall() || obj->getClass() == &js_DeclEnvClass); - - const Value &v = *vp; - - JSObject *funobj; - if (IsFunctionObject(v, &funobj)) { - JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); - - /* - * Any escaping null or flat closure that reaches above itself or - * contains nested functions that reach above it must be wrapped. - * We can wrap only when this Call or Declarative Environment obj - * still has an active stack frame associated with it. - */ - if (fun->needsWrapper()) { - LeaveTrace(cx); - - StackFrame *fp = (StackFrame *) obj->getPrivate(); - if (fp) { - JSObject *wrapper = WrapEscapingClosure(cx, fp, fun); - if (!wrapper) - return false; - vp->setObject(*wrapper); - return true; - } - - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_OPTIMIZED_CLOSURE_LEAK); - return false; - } - } - return true; -} - -static JSBool -CalleeGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) -{ - return CheckForEscapingClosure(cx, obj, vp); -} - /* * Construct a call object for the given bindings. If this is a call object * for a function invocation, callee should be the function being called. @@ -1036,7 +825,7 @@ CreateFunCallObject(JSContext *cx, StackFrame *fp) return NULL; if (!DefineNativeProperty(cx, scopeChain, ATOM_TO_JSID(lambdaName), - ObjectValue(fp->callee()), CalleeGetter, NULL, + ObjectValue(fp->callee()), NULL, NULL, JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) { return NULL; } @@ -1269,19 +1058,9 @@ GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp) *vp = fp->varSlot(i); else *vp = obj->callObjVar(i); - return true; } -JSBool -GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, Value *vp) -{ - if (!GetCallVar(cx, obj, id, vp)) - return false; - - return CheckForEscapingClosure(cx, obj, vp); -} - JSBool SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) { @@ -1432,21 +1211,6 @@ StackFrame::getValidCalleeObject(JSContext *cx, Value *vp) } JSFunction *fun = this->fun(); - - /* - * See the equivalent condition in ArgGetter for the 'callee' id case, but - * note that here we do not want to throw, since this escape can happen via - * a foo.caller reference alone, without any debugger or indirect eval. And - * alas, it seems foo.caller is still used on the Web. - */ - if (fun->needsWrapper()) { - JSObject *wrapper = WrapEscapingClosure(cx, this, fun); - if (!wrapper) - return false; - vp->setObject(*wrapper); - return true; - } - JSObject &funobj = callee(); vp->setObject(funobj); @@ -2796,16 +2560,6 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen) return closure; } -JSObject * -js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun) -{ - JS_ASSERT(cx->fp()->fun()->flags & JSFUN_HEAVYWEIGHT); - JS_ASSERT(!cx->fp()->fun()->optimizedClosure()); - JS_ASSERT(FUN_FLAT_CLOSURE(fun)); - - return WrapEscapingClosure(cx, cx->fp(), fun); -} - JSFunction * js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, Native native, uintN nargs, uintN attrs) diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 8ab3877f88de..5a712afad17d 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -146,7 +146,6 @@ struct JSFunction : public JSObject_Slots2 JSAtom *atom; /* name for diagnostics and decompiling */ bool optimizedClosure() const { return FUN_KIND(this) > JSFUN_INTERPRETED; } - bool needsWrapper() const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; } bool isInterpreted() const { return FUN_INTERPRETED(this); } bool isNative() const { return !FUN_INTERPRETED(this); } bool isConstructor() const { return flags & JSFUN_CONSTRUCTOR; } @@ -481,9 +480,6 @@ js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain); extern JSObject * js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen); -extern JS_REQUIRES_STACK JSObject * -js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun); - extern JSFunction * js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, js::Native native, uintN nargs, uintN flags); @@ -530,13 +526,6 @@ GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); extern JSBool GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); -/* - * Slower version of js_GetCallVar used when call_resolve detects an attempt to - * leak an optimized closure via indirect or debugger eval. - */ -extern JSBool -GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); - extern JSBool GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index bc8a806d09f2..8493165c7827 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1598,19 +1598,11 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, FrameRegs& regs, * same way as non-call bytecodes. */ JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH); -JS_STATIC_ASSERT(JSOP_GETUPVAR_DBG_LENGTH == JSOP_GETFCSLOT_LENGTH); -JS_STATIC_ASSERT(JSOP_GETUPVAR_DBG_LENGTH == JSOP_CALLUPVAR_DBG_LENGTH); JS_STATIC_ASSERT(JSOP_GETFCSLOT_LENGTH == JSOP_CALLFCSLOT_LENGTH); JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH); JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH); JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH); -/* - * Same for debuggable flat closures defined at top level in another function - * or program fragment. - */ -JS_STATIC_ASSERT(JSOP_DEFFUN_FC_LENGTH == JSOP_DEFFUN_DBGFC_LENGTH); - /* * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but * remain distinct for the decompiler. Likewise for JSOP_INIT{PROP,METHOD}. @@ -4582,47 +4574,6 @@ BEGIN_CASE(JSOP_SETLOCAL) } END_SET_CASE(JSOP_SETLOCAL) -BEGIN_CASE(JSOP_GETUPVAR_DBG) -BEGIN_CASE(JSOP_CALLUPVAR_DBG) -{ - JSFunction *fun = regs.fp()->fun(); - JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED); - JS_ASSERT(fun->u.i.wrapper); - - /* Scope for tempPool mark and local names allocation in it. */ - JSObject *obj, *obj2; - JSProperty *prop; - jsid id; - JSAtom *atom; - { - Vector names(cx); - if (!fun->script()->bindings.getLocalNameArray(cx, &names)) - goto error; - - uintN index = fun->script()->bindings.countArgsAndVars() + GET_UINT16(regs.pc); - atom = names[index]; - id = ATOM_TO_JSID(atom); - - if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) - goto error; - } - - if (!prop) { - atomNotDefined = atom; - goto atom_not_defined; - } - - /* Minimize footprint with generic code instead of NATIVE_GET. */ - Value *vp = regs.sp; - PUSH_NULL(); - if (!obj->getProperty(cx, id, vp)) - goto error; - - if (op == JSOP_CALLUPVAR_DBG) - PUSH_UNDEFINED(); -} -END_CASE(JSOP_GETUPVAR_DBG) - BEGIN_CASE(JSOP_GETFCSLOT) BEGIN_CASE(JSOP_CALLFCSLOT) { @@ -4807,14 +4758,11 @@ BEGIN_CASE(JSOP_DEFFUN) END_CASE(JSOP_DEFFUN) BEGIN_CASE(JSOP_DEFFUN_FC) -BEGIN_CASE(JSOP_DEFFUN_DBGFC) { JSFunction *fun; LOAD_FUNCTION(0); - JSObject *obj = (op == JSOP_DEFFUN_FC) - ? js_NewFlatClosure(cx, fun, JSOP_DEFFUN_FC, JSOP_DEFFUN_FC_LENGTH) - : js_NewDebuggableFlatClosure(cx, fun); + JSObject *obj = js_NewFlatClosure(cx, fun, JSOP_DEFFUN_FC, JSOP_DEFFUN_FC_LENGTH); if (!obj) goto error; @@ -4897,20 +4845,6 @@ BEGIN_CASE(JSOP_DEFLOCALFUN_FC) } END_CASE(JSOP_DEFLOCALFUN_FC) -BEGIN_CASE(JSOP_DEFLOCALFUN_DBGFC) -{ - JSFunction *fun; - LOAD_FUNCTION(SLOTNO_LEN); - - JSObject *obj = js_NewDebuggableFlatClosure(cx, fun); - if (!obj) - goto error; - - uint32 slot = GET_SLOTNO(regs.pc); - regs.fp()->slots()[slot].setObject(*obj); -} -END_CASE(JSOP_DEFLOCALFUN_DBGFC) - BEGIN_CASE(JSOP_LAMBDA) { /* Load the specified function object literal. */ @@ -5024,19 +4958,6 @@ BEGIN_CASE(JSOP_LAMBDA_FC) } END_CASE(JSOP_LAMBDA_FC) -BEGIN_CASE(JSOP_LAMBDA_DBGFC) -{ - JSFunction *fun; - LOAD_FUNCTION(0); - - JSObject *obj = js_NewDebuggableFlatClosure(cx, fun); - if (!obj) - goto error; - - PUSH_OBJECT(*obj); -} -END_CASE(JSOP_LAMBDA_DBGFC) - BEGIN_CASE(JSOP_CALLEE) JS_ASSERT(regs.fp()->isNonEvalFunctionFrame()); PUSH_COPY(argv[-2]); diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 19c05eb49c82..de45e73e1ddd 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -2915,8 +2915,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) break; } - case JSOP_GETUPVAR_DBG: - case JSOP_CALLUPVAR_DBG: case JSOP_GETFCSLOT: case JSOP_CALLFCSLOT: { @@ -4099,7 +4097,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) case JSOP_LAMBDA: case JSOP_LAMBDA_FC: - case JSOP_LAMBDA_DBGFC: #if JS_HAS_GENERATOR_EXPRS sn = js_GetSrcNote(jp->script, pc); if (sn && SN_TYPE(sn) == SRC_GENEXP) { @@ -4488,7 +4485,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) case JSOP_DEFFUN: case JSOP_DEFFUN_FC: - case JSOP_DEFFUN_DBGFC: LOAD_FUNCTION(0); todo = -2; goto do_function; diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index ea6348d13803..927d04debfb6 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -589,30 +589,21 @@ OPDEF(JSOP_OBJTOP, 228,"objtop", NULL, 3, 0, 0, 0, JOF_UINT16 /* This opcode stores an index that is unique to the given loop. */ OPDEF(JSOP_TRACE, 229, "trace", NULL, 3, 0, 0, 0, JOF_UINT16) -/* - * Debugger versions of the flat closure (_FC) ops. - */ -OPDEF(JSOP_GETUPVAR_DBG, 230,"getupvar_dbg", NULL, 3, 0, 1, 19, JOF_UINT16|JOF_NAME) -OPDEF(JSOP_CALLUPVAR_DBG, 231,"callupvar_dbg", NULL, 3, 0, 2, 19, JOF_UINT16|JOF_NAME|JOF_CALLOP) -OPDEF(JSOP_DEFFUN_DBGFC, 232,"deffun_dbgfc", NULL, 3, 0, 0, 0, JOF_OBJECT|JOF_DECLARING) -OPDEF(JSOP_DEFLOCALFUN_DBGFC,233,"deflocalfun_dbgfc",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT) -OPDEF(JSOP_LAMBDA_DBGFC, 234,"lambda_dbgfc", NULL, 3, 0, 1, 19, JOF_OBJECT) - /* * Joined function object as method optimization support. */ -OPDEF(JSOP_SETMETHOD, 235,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) -OPDEF(JSOP_INITMETHOD, 236,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) -OPDEF(JSOP_UNBRAND, 237,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE) -OPDEF(JSOP_UNBRANDTHIS, 238,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE) +OPDEF(JSOP_SETMETHOD, 230,"setmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) +OPDEF(JSOP_INITMETHOD, 231,"initmethod", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) +OPDEF(JSOP_UNBRAND, 232,"unbrand", NULL, 1, 1, 1, 0, JOF_BYTE) +OPDEF(JSOP_UNBRANDTHIS, 233,"unbrandthis", NULL, 1, 0, 0, 0, JOF_BYTE) -OPDEF(JSOP_SHARPINIT, 239,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT) +OPDEF(JSOP_SHARPINIT, 234,"sharpinit", NULL, 3, 0, 0, 0, JOF_UINT16|JOF_SHARPSLOT) /* Static binding for globals. */ -OPDEF(JSOP_GETGLOBAL, 240,"getglobal", NULL, 3, 0, 1, 19, JOF_GLOBAL|JOF_NAME) -OPDEF(JSOP_CALLGLOBAL, 241,"callglobal", NULL, 3, 0, 2, 19, JOF_GLOBAL|JOF_NAME|JOF_CALLOP) +OPDEF(JSOP_GETGLOBAL, 235,"getglobal", NULL, 3, 0, 1, 19, JOF_GLOBAL|JOF_NAME) +OPDEF(JSOP_CALLGLOBAL, 236,"callglobal", NULL, 3, 0, 2, 19, JOF_GLOBAL|JOF_NAME|JOF_CALLOP) /* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */ -OPDEF(JSOP_FUNCALL, 242,"funcall", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE) +OPDEF(JSOP_FUNCALL, 237,"funcall", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE) -OPDEF(JSOP_FORGNAME, 243,"forgname", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_GNAME|JOF_FOR|JOF_TMPSLOT3) +OPDEF(JSOP_FORGNAME, 238,"forgname", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_GNAME|JOF_FOR|JOF_TMPSLOT3) diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 6a21c0fec354..d32cb82dcc33 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -8222,8 +8222,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, JS_ASSERT(slot < cfp->numFormalArgs()); vp = &cfp->formalArg(slot); nr.v = *vp; - } else if (shape->getterOp() == GetCallVar || - shape->getterOp() == GetCallVarChecked) { + } else if (shape->getterOp() == GetCallVar) { JS_ASSERT(slot < cfp->numSlots()); vp = &cfp->slots()[slot]; nr.v = *vp; @@ -8268,8 +8267,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, if (shape->getterOp() == GetCallArg) { JS_ASSERT(slot < ArgClosureTraits::slot_count(obj)); slot += ArgClosureTraits::slot_offset(obj); - } else if (shape->getterOp() == GetCallVar || - shape->getterOp() == GetCallVarChecked) { + } else if (shape->getterOp() == GetCallVar) { JS_ASSERT(slot < VarClosureTraits::slot_count(obj)); slot += VarClosureTraits::slot_offset(obj); } else { @@ -8302,14 +8300,12 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp, cx_ins }; const CallInfo* ci; - if (shape->getterOp() == GetCallArg) { + if (shape->getterOp() == GetCallArg) ci = &GetClosureArg_ci; - } else if (shape->getterOp() == GetCallVar || - shape->getterOp() == GetCallVarChecked) { + else if (shape->getterOp() == GetCallVar) ci = &GetClosureVar_ci; - } else { + else RETURN_STOP("dynamic property of Call object"); - } // Now assert that our use of shape->shortid was in fact kosher. JS_ASSERT(shape->hasShortID()); @@ -16570,19 +16566,6 @@ TraceRecorder::record_JSOP_CALLGNAME() return record_JSOP_CALLNAME(); } -#define DBG_STUB(OP) \ - JS_REQUIRES_STACK AbortableRecordingStatus \ - TraceRecorder::record_##OP() \ - { \ - RETURN_STOP_A("can't trace " #OP); \ - } - -DBG_STUB(JSOP_GETUPVAR_DBG) -DBG_STUB(JSOP_CALLUPVAR_DBG) -DBG_STUB(JSOP_DEFFUN_DBGFC) -DBG_STUB(JSOP_DEFLOCALFUN_DBGFC) -DBG_STUB(JSOP_LAMBDA_DBGFC) - #ifdef JS_JIT_SPEW /* * Print information about entry typemaps and unstable exits for all peers diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index bc4201d4080b..9bd0c37162d1 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -222,7 +222,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 89) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 90) /* * Library-private functions. From c1109a347199d4421db4d607355610a87d231843 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 8 Jul 2011 13:55:03 -0400 Subject: [PATCH 06/15] Bug 481962 - Force logging on in imagelib. r=joe --HG-- extra : rebase_source : 110c088d4221d56aede72808e05c202a7e2a3f91 --- modules/libpr0n/decoders/nsBMPDecoder.cpp | 3 +-- modules/libpr0n/decoders/nsJPEGDecoder.cpp | 2 +- modules/libpr0n/decoders/nsPNGDecoder.cpp | 1 + modules/libpr0n/public/ImageLogging.h | 22 +++++++++++++++++++--- modules/libpr0n/src/RasterImage.cpp | 1 - modules/libpr0n/src/imgLoader.cpp | 2 +- modules/libpr0n/src/imgRequest.cpp | 2 +- 7 files changed, 24 insertions(+), 9 deletions(-) diff --git a/modules/libpr0n/decoders/nsBMPDecoder.cpp b/modules/libpr0n/decoders/nsBMPDecoder.cpp index 6d4c69c7d7b7..c4af7ec37bef 100644 --- a/modules/libpr0n/decoders/nsBMPDecoder.cpp +++ b/modules/libpr0n/decoders/nsBMPDecoder.cpp @@ -48,8 +48,7 @@ #include "nsIInputStream.h" #include "RasterImage.h" #include "imgIContainerObserver.h" - -#include "prlog.h" +#include "ImageLogging.h" namespace mozilla { namespace imagelib { diff --git a/modules/libpr0n/decoders/nsJPEGDecoder.cpp b/modules/libpr0n/decoders/nsJPEGDecoder.cpp index cfd81a1994d5..a9cdf9371a9c 100644 --- a/modules/libpr0n/decoders/nsJPEGDecoder.cpp +++ b/modules/libpr0n/decoders/nsJPEGDecoder.cpp @@ -40,6 +40,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsJPEGDecoder.h" +#include "ImageLogging.h" #include "imgIContainerObserver.h" @@ -47,7 +48,6 @@ #include "nspr.h" #include "nsCRT.h" -#include "ImageLogging.h" #include "gfxColor.h" #include "jerror.h" diff --git a/modules/libpr0n/decoders/nsPNGDecoder.cpp b/modules/libpr0n/decoders/nsPNGDecoder.cpp index 1e9de136defe..33871a8d76f7 100644 --- a/modules/libpr0n/decoders/nsPNGDecoder.cpp +++ b/modules/libpr0n/decoders/nsPNGDecoder.cpp @@ -42,6 +42,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsPNGDecoder.h" +#include "ImageLogging.h" #include "nsMemory.h" #include "nsRect.h" diff --git a/modules/libpr0n/public/ImageLogging.h b/modules/libpr0n/public/ImageLogging.h index ea1bbcd25d10..328c25808268 100644 --- a/modules/libpr0n/public/ImageLogging.h +++ b/modules/libpr0n/public/ImageLogging.h @@ -37,12 +37,25 @@ * * ***** END LICENSE BLOCK ***** */ +#ifndef ImageLogging_h +#define ImageLogging_h + +// In order for FORCE_PR_LOG below to work, we have to define it before the +// first time prlog is #included. +#if defined(PR_LOG) +#error "Must #include ImageLogging.h before before any IPDL-generated files or other files that #include prlog.h." +#endif + +#if defined(MOZ_LOGGING) +#define FORCE_PR_LOG +#endif + #include "prlog.h" #include "prinrval.h" - #include "nsString.h" #if defined(PR_LOGGING) +// Declared in imgRequest.cpp. extern PRLogModuleInfo *gImgLog; #define GIVE_ME_MS_NOW() PR_IntervalToMilliseconds(PR_IntervalNow()) @@ -212,8 +225,8 @@ public: NS_LITERAL_CSTRING(s), \ NS_LITERAL_CSTRING(m)) - #else + #define LOG_SCOPE(l, s) #define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) #define LOG_FUNC(l, s) @@ -221,6 +234,9 @@ public: #define LOG_STATIC_FUNC(l, s) #define LOG_STATIC_FUNC_WITH_PARAM(l, s, pn, pv) #define LOG_MSG(l, s, m) -#endif + +#endif // if defined(PR_LOGGING) #define LOG_MSG_WITH_PARAM LOG_FUNC_WITH_PARAM + +#endif // ifndef ImageLogging_h diff --git a/modules/libpr0n/src/RasterImage.cpp b/modules/libpr0n/src/RasterImage.cpp index eeaff40bf5b7..6414eeb79c1a 100644 --- a/modules/libpr0n/src/RasterImage.cpp +++ b/modules/libpr0n/src/RasterImage.cpp @@ -53,7 +53,6 @@ #include "nsAutoPtr.h" #include "nsStringStream.h" #include "prmem.h" -#include "prlog.h" #include "prenv.h" #include "nsTime.h" #include "ImageLogging.h" diff --git a/modules/libpr0n/src/imgLoader.cpp b/modules/libpr0n/src/imgLoader.cpp index c692aa6b0254..71ca5c96da13 100644 --- a/modules/libpr0n/src/imgLoader.cpp +++ b/modules/libpr0n/src/imgLoader.cpp @@ -37,6 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ +#include "ImageLogging.h" #include "imgLoader.h" #include "imgRequestProxy.h" @@ -71,7 +72,6 @@ #include "netCore.h" #include "nsURILoader.h" -#include "ImageLogging.h" #include "nsIComponentRegistrar.h" diff --git a/modules/libpr0n/src/imgRequest.cpp b/modules/libpr0n/src/imgRequest.cpp index 44d2521b546f..3c840ad88231 100644 --- a/modules/libpr0n/src/imgRequest.cpp +++ b/modules/libpr0n/src/imgRequest.cpp @@ -39,6 +39,7 @@ * ***** END LICENSE BLOCK ***** */ #include "imgRequest.h" +#include "ImageLogging.h" /* We end up pulling in windows.h because we eventually hit gfxWindowsSurface; * windows.h defines LoadImage, so we have to #undef it or imgLoader::LoadImage @@ -54,7 +55,6 @@ #include "VectorImage.h" #include "imgILoader.h" -#include "ImageLogging.h" #include "netCore.h" From 079f214b294bf5ce0da404dbbb1bdfb98d734ad1 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Jul 2011 17:57:59 +0200 Subject: [PATCH 07/15] Bug 670905 - Update mingw cofigure checks to current version (r=khuey) --- configure.in | 5 ++--- js/src/configure.in | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/configure.in b/configure.in index 61577a85808a..3af191e8426c 100644 --- a/configure.in +++ b/configure.in @@ -123,7 +123,7 @@ CAIRO_VERSION=1.10 PANGO_VERSION=1.14.0 GTK2_VERSION=2.10.0 WINDRES_VERSION=2.14.90 -W32API_VERSION=3.8 +W32API_VERSION=3.14 GNOMEVFS_VERSION=2.0 GNOMEUI_VERSION=2.2.0 GCONF_VERSION=1.2.1 @@ -870,8 +870,7 @@ EOF AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.]) fi - # Server 2003 is the highest version supported - MOZ_WINSDK_MAXVER=0x05020000 + MOZ_WINSDK_MAXVER=0x06010000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) diff --git a/js/src/configure.in b/js/src/configure.in index d3b44c582e3a..8b12bbb991a4 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -112,7 +112,7 @@ dnl ======================================================== PERL_VERSION=5.006 PYTHON_VERSION=2.5 WINDRES_VERSION=2.14.90 -W32API_VERSION=3.8 +W32API_VERSION=3.14 MSMANIFEST_TOOL= @@ -871,8 +871,7 @@ EOF AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.]) fi - # Server 2003 is the highest version supported - MOZ_WINSDK_MAXVER=0x05020000 + MOZ_WINSDK_MAXVER=0x06010000 fi # !GNU_CC AC_DEFINE_UNQUOTED(WINVER,0x$WINVER) From 99f37a11dbd12758a04f926fbb194fa214a60dc7 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Jul 2011 17:58:17 +0200 Subject: [PATCH 08/15] Bug 670913 - LayerManagerD3D10.h fails to compile on mingw (r=joe) --- gfx/layers/d3d10/LayerManagerD3D10.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/layers/d3d10/LayerManagerD3D10.h b/gfx/layers/d3d10/LayerManagerD3D10.h index 473604036e83..d1efd8f07255 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.h +++ b/gfx/layers/d3d10/LayerManagerD3D10.h @@ -169,7 +169,7 @@ public: */ Nv3DVUtils *GetNv3DVUtils() { return mNv3DVUtils; } - static void LayerManagerD3D10::ReportFailure(const nsACString &aMsg, HRESULT aCode); + static void ReportFailure(const nsACString &aMsg, HRESULT aCode); private: void SetupPipeline(); From fda447618916cc11384adb73812a5fbb7624e3e5 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Jul 2011 17:58:33 +0200 Subject: [PATCH 09/15] Bug 669875 - Broken widget/src/windows cross compilation on case sensitive OSes (r=jmathies) --- widget/src/windows/AudioSession.cpp | 4 ++-- widget/src/windows/TaskbarTabPreview.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/widget/src/windows/AudioSession.cpp b/widget/src/windows/AudioSession.cpp index 54120abd6406..83116aad05b9 100644 --- a/widget/src/windows/AudioSession.cpp +++ b/widget/src/windows/AudioSession.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include "nsIStringBundle.h" #include "nsIUUIDGenerator.h" @@ -51,7 +51,7 @@ #include "nsAutoPtr.h" #include "nsServiceManagerUtils.h" #include "nsString.h" -#include "nsXULAppApi.h" +#include "nsXULAppAPI.h" #include diff --git a/widget/src/windows/TaskbarTabPreview.cpp b/widget/src/windows/TaskbarTabPreview.cpp index f742a002298a..3ec016e46982 100644 --- a/widget/src/windows/TaskbarTabPreview.cpp +++ b/widget/src/windows/TaskbarTabPreview.cpp @@ -41,7 +41,7 @@ #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7 #include "TaskbarTabPreview.h" -#include "nsWindowGFX.h" +#include "nsWindowGfx.h" #include "nsUXThemeData.h" #include From 3743f9de6b97b6c8dea70e0f147be3b02c25fe82 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Jul 2011 17:58:49 +0200 Subject: [PATCH 10/15] Bug 669881 - Compile nsDownloadScanner.cpp on mingw (r=jmathies) --- toolkit/components/downloads/Makefile.in | 2 -- .../components/downloads/nsDownloadScanner.cpp | 16 ++++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/toolkit/components/downloads/Makefile.in b/toolkit/components/downloads/Makefile.in index 968099e53d0d..5620a19d9419 100644 --- a/toolkit/components/downloads/Makefile.in +++ b/toolkit/components/downloads/Makefile.in @@ -59,11 +59,9 @@ CPPSRCS = \ nsDownloadManager.cpp \ $(NULL) -ifndef GNU_CXX ifeq ($(OS_ARCH),WINNT) CPPSRCS += nsDownloadScanner.cpp endif -endif # definition of MOZ_SUITE is only added via config.mk include $(topsrcdir)/config/config.mk diff --git a/toolkit/components/downloads/nsDownloadScanner.cpp b/toolkit/components/downloads/nsDownloadScanner.cpp index d61c081345cb..a454710f724b 100644 --- a/toolkit/components/downloads/nsDownloadScanner.cpp +++ b/toolkit/components/downloads/nsDownloadScanner.cpp @@ -480,10 +480,10 @@ nsDownloadScanner::Scan::DoScanAES() #pragma warning(disable: 4509) HRESULT hr; nsRefPtr ae; - __try { + MOZ_SEH_TRY { hr = CoCreateInstance(CLSID_AttachmentServices, NULL, CLSCTX_ALL, IID_IAttachmentExecute, getter_AddRefs(ae)); - } __except(ExceptionFilterFunction(GetExceptionCode())) { + } MOZ_SEH_EXCEPT(ExceptionFilterFunction(GetExceptionCode())) { return CheckAndSetState(AVSCAN_NOTSTARTED,AVSCAN_FAILED); } @@ -492,7 +492,7 @@ nsDownloadScanner::Scan::DoScanAES() AVScanState newState; if (SUCCEEDED(hr)) { PRBool gotException = PR_FALSE; - __try { + MOZ_SEH_TRY { (void)ae->SetClientGuid(GUID_MozillaVirusScannerPromptGeneric); (void)ae->SetLocalPath(mPath.BeginWriting()); // Provide the src for everything but data: schemes. @@ -501,13 +501,13 @@ nsDownloadScanner::Scan::DoScanAES() // Save() will invoke the scanner hr = ae->Save(); - } __except(ExceptionFilterFunction(GetExceptionCode())) { + } MOZ_SEH_EXCEPT(ExceptionFilterFunction(GetExceptionCode())) { gotException = PR_TRUE; } - __try { + MOZ_SEH_TRY { ae = NULL; - } __except(ExceptionFilterFunction(GetExceptionCode())) { + } MOZ_SEH_EXCEPT(ExceptionFilterFunction(GetExceptionCode())) { gotException = PR_TRUE; } @@ -555,9 +555,9 @@ nsDownloadScanner::Scan::DoScan() } } - __try { + MOZ_SEH_TRY { CoUninitialize(); - } __except(ExceptionFilterFunction(GetExceptionCode())) { + } MOZ_SEH_EXCEPT(ExceptionFilterFunction(GetExceptionCode())) { // Not much we can do at this point... } } From 49858f3eadad9b4d9b4f6d716c3b9b32c2f2f21e Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 13 Jul 2011 18:03:44 +0200 Subject: [PATCH 11/15] Bug 621367 - nsPermissionManager doesn't allow enumerator access in content processes (r=dwitte) --- extensions/cookie/nsPermissionManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 773a97317773..f85221811170 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -790,8 +790,6 @@ AddPermissionsToList(nsHostEntry *entry, void *arg) NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) { - ENSURE_NOT_CHILD_PROCESS; - // roll an nsCOMArray of all our permissions, then hand out an enumerator nsCOMArray array; nsGetEnumeratorData data(&array, &mTypeArray); From b3d27690c6d3d7efc277234fa49f1f8d7cb52884 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Wed, 13 Jul 2011 12:52:02 -0400 Subject: [PATCH 12/15] No bug - Fix Vim modeline in PluginModuleChild.cpp. rs=khuey DONTBUILD --HG-- extra : rebase_source : ec84b4b231784a111375092339b4b0404570fb47 --- dom/plugins/ipc/PluginModuleChild.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp index 7ee55b6261d1..dae3f354c3a4 100644 --- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -1,5 +1,5 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: sw=4 ts=4 et : */ +/* vim: set sw=4 ts=4 et : */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * From a7f6c3ef8c73a291d6a4a26213bef76eee05dba2 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 15 Jun 2011 10:15:37 -0700 Subject: [PATCH 13/15] Bug 670779 - Add LinkConstructorAndPrototype to encapsulate adding ctor.prototype and ctor.prototype.constructor. r=bhackett --HG-- extra : rebase_source : 1216c2c096b866c94205c3f53fe0dd70225523c4 --- js/src/jsfun.cpp | 28 ++++++++++++++++------------ js/src/jsobj.cpp | 27 +-------------------------- js/src/jsobj.h | 4 ---- js/src/jsregexp.cpp | 11 +++-------- js/src/jsstr.cpp | 11 +++-------- js/src/jsxml.cpp | 5 ++--- js/src/vm/GlobalObject.cpp | 10 ++++++++++ js/src/vm/GlobalObject.h | 8 ++++++++ 8 files changed, 43 insertions(+), 61 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index ce6044b8cf73..b945273044c8 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1447,15 +1447,20 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj) return NULL; /* - * ECMA (15.3.5.2) says that a user-defined function's .prototype property - * is non-configurable, non-enumerable, and (initially) writable. Hence - * JSPROP_PERMANENT below. By contrast, the built-in constructors, such as - * Object (15.2.3.1) and Function (15.3.3.1), have non-writable - * .prototype properties. Those are eagerly defined, with attributes - * JSPROP_PERMANENT | JSPROP_READONLY, in js_InitClass. + * Per ES5 15.3.5.2 a user-defined function's .prototype property is + * initially non-configurable, non-enumerable, and writable. Per ES5 13.2 + * the prototype's .constructor property is configurable, non-enumerable, + * and writable. */ - if (!js_SetClassPrototype(cx, obj, proto, JSPROP_PERMANENT)) - return NULL; + if (!obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), + ObjectValue(*proto), PropertyStub, StrictPropertyStub, + JSPROP_PERMANENT) || + !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), + ObjectValue(*obj), PropertyStub, StrictPropertyStub, 0)) + { + return NULL; + } + return proto; } @@ -1471,12 +1476,11 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, if (JSID_IS_ATOM(id, cx->runtime->atomState.classPrototypeAtom)) { /* * Native or "built-in" functions do not have a .prototype property per - * ECMA-262 (all editions). Built-in constructor functions, e.g. Object - * and Function to name two conspicuous examples, do have a .prototype - * property, but it is created eagerly by js_InitClass (jsobj.cpp). + * ECMA-262, or (Object.prototype, Function.prototype, etc.) have that + * property created eagerly. * * ES5 15.3.4: the non-native function object named Function.prototype - * must not have a .prototype property. + * does not have a .prototype property. * * ES5 15.3.4.5: bound functions don't have a prototype property. The * isNative() test covers this case because bound functions are native diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 57f538ae91f1..d2fd083011c9 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3829,11 +3829,8 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt proto = &rval.toObject(); } - /* Connect constructor and prototype by named properties. */ - if (!js_SetClassPrototype(cx, ctor, proto, - JSPROP_READONLY | JSPROP_PERMANENT)) { + if (!LinkConstructorAndPrototype(cx, ctor, proto)) goto bad; - } /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ if (ctor->getClass() == clasp) @@ -6106,28 +6103,6 @@ js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey, return FindClassPrototype(cx, scopeobj, protoKey, protop, clasp); } -JSBool -js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs) -{ - /* - * Use the given attributes for the prototype property of the constructor, - * as user-defined constructors have a DontDelete prototype (which may be - * reset), while native or "system" constructors have DontEnum | ReadOnly | - * DontDelete. - */ - if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), - ObjectOrNullValue(proto), PropertyStub, StrictPropertyStub, attrs)) { - return JS_FALSE; - } - - /* - * ECMA says that Object.prototype.constructor, or f.prototype.constructor - * for a user-defined function f, is DontEnum. - */ - return proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), - ObjectOrNullValue(ctor), PropertyStub, StrictPropertyStub, 0); -} - JSObject * PrimitiveToObject(JSContext *cx, const Value &v) { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 9bc92ae9cb38..9848e7b9f316 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1762,10 +1762,6 @@ extern JS_FRIEND_API(JSBool) js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop, js::Class *clasp = NULL); -extern JSBool -js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, - uintN attrs); - /* * Wrap boolean, number or string as Boolean, Number or String object. * *vp must not be an object, null or undefined. diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index ef82629f59c9..c23f6c9944f1 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -57,6 +57,8 @@ #include "jsstr.h" #include "jsvector.h" +#include "vm/GlobalObject.h" + #include "jsobjinlines.h" #include "jsregexpinlines.h" @@ -857,14 +859,8 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj) /* RegExp creates regular expressions. */ FUN_CLASP(ctor) = &js_RegExpClass; - /* Define RegExp.prototype and RegExp.prototype.constructor. */ - if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), - ObjectValue(*proto), PropertyStub, StrictPropertyStub, - JSPROP_PERMANENT | JSPROP_READONLY) || - !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), - ObjectValue(*ctor), PropertyStub, StrictPropertyStub, 0)) { + if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; - } /* Add static properties to the RegExp constructor. */ if (!JS_DefineProperties(cx, ctor, regexp_static_props) || @@ -883,4 +879,3 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj) return proto; } - diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index f83abc4a6e31..3134a13d0545 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -76,6 +76,8 @@ #include "jsvector.h" #include "jsversion.h" +#include "vm/GlobalObject.h" + #include "jsinterpinlines.h" #include "jsobjinlines.h" #include "jsregexpinlines.h" @@ -3183,15 +3185,8 @@ js_InitStringClass(JSContext *cx, JSObject *obj) /* String creates string objects. */ FUN_CLASP(ctor) = &js_StringClass; - /* Define String.prototype and String.prototype.constructor. */ - if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), - ObjectValue(*proto), PropertyStub, StrictPropertyStub, - JSPROP_PERMANENT | JSPROP_READONLY) || - !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), - ObjectValue(*ctor), PropertyStub, StrictPropertyStub, 0)) - { + if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; - } /* Add properties and methods to the prototype and the constructor. */ if (!JS_DefineFunctions(cx, proto, string_methods) || diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 943397579efc..99326cc1c3f7 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -7160,10 +7160,9 @@ js_InitXMLClass(JSContext *cx, JSObject *obj) JSFunction *fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, JSFUN_CONSTRUCTOR); if (!fun) return NULL; - if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto, - JSPROP_READONLY | JSPROP_PERMANENT)) { + if (!LinkConstructorAndPrototype(cx, FUN_OBJECT(fun), proto)) return NULL; - } + return proto; } diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index d3284d9679f5..3a4ab2976659 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -226,4 +226,14 @@ GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp) return proto; } +bool +LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto) +{ + return ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), + ObjectValue(*proto), PropertyStub, StrictPropertyStub, + JSPROP_PERMANENT | JSPROP_READONLY) && + proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), + ObjectValue(*ctor), PropertyStub, StrictPropertyStub, 0); +} + } // namespace js diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index e820f15bd0ba..7f3d233cd6b4 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -162,6 +162,14 @@ class GlobalObject : public ::JSObject { bool initStandardClasses(JSContext *cx); }; +/* + * Define ctor.prototype = proto as non-enumerable, non-configurable, and + * non-writable; define proto.constructor = ctor as non-enumerable but + * configurable and writable. + */ +extern bool +LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto); + } // namespace js js::GlobalObject * From 8e8cf3d389ce3d289dc57e0e7b775a699392e8c6 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 13 Jun 2011 11:52:45 -0700 Subject: [PATCH 14/15] Bug 671082 - Add GlobalObject::createConstructor to abstract creation of constructors, after basic primordials are installed in the global. r=bhackett --HG-- extra : rebase_source : 7d912d659f18bd4a24cb9e285dc71cbb0eac9858 --- js/src/jsobj.cpp | 17 +++++++++-------- js/src/jsregexp.cpp | 10 ++-------- js/src/jsstr.cpp | 8 ++------ js/src/vm/GlobalObject.cpp | 16 ++++++++++++++++ js/src/vm/GlobalObject.h | 7 +++++++ 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index d2fd083011c9..f4f20cc7cb1a 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3797,21 +3797,22 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt ctor = proto; } else { - JSFunction *fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom); + /* + * Create the constructor, not using GlobalObject::createConstructor + * because the constructor currently must have |obj| as its parent. + * (FIXME: remove this dependency on the exact identity of the parent, + * perhaps as part of bug 638316.) + */ + JSFunction *fun = + js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom); if (!fun) goto bad; + FUN_CLASP(fun) = clasp; AutoValueRooter tvr2(cx, ObjectValue(*fun)); if (!DefineStandardSlot(cx, obj, key, atom, tvr2.value(), 0, named)) goto bad; - /* - * Remember the class this function is a constructor for so that - * we know to create an object of this class when we call the - * constructor. - */ - FUN_CLASP(fun) = clasp; - /* * Optionally construct the prototype object, before the class has * been fully initialized. Allow the ctor to replace proto with a diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index c23f6c9944f1..2adb41bdb75f 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -849,16 +849,11 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj) return NULL; proto->brand(cx); - /* Create the RegExp constructor. */ - JSAtom *regExpAtom = CLASS_ATOM(cx, RegExp); - JSFunction *ctor = - js_NewFunction(cx, NULL, regexp_construct, 2, JSFUN_CONSTRUCTOR, global, regExpAtom); + JSFunction *ctor = global->createConstructor(cx, regexp_construct, &js_RegExpClass, + CLASS_ATOM(cx, RegExp), 2); if (!ctor) return NULL; - /* RegExp creates regular expressions. */ - FUN_CLASP(ctor) = &js_RegExpClass; - if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; @@ -873,7 +868,6 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj) return NULL; } - /* Install the fully-constructed RegExp and RegExp.prototype in global. */ if (!DefineConstructorAndPrototype(cx, global, JSProto_RegExp, ctor, proto)) return NULL; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 3134a13d0545..e773894331a5 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3177,14 +3177,11 @@ js_InitStringClass(JSContext *cx, JSObject *obj) return NULL; /* Now create the String function. */ - JSAtom *atom = CLASS_ATOM(cx, String); - JSFunction *ctor = js_NewFunction(cx, NULL, js_String, 1, JSFUN_CONSTRUCTOR, global, atom); + JSFunction *ctor = global->createConstructor(cx, js_String, &js_StringClass, + CLASS_ATOM(cx, String), 1); if (!ctor) return NULL; - /* String creates string objects. */ - FUN_CLASP(ctor) = &js_StringClass; - if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; @@ -3199,7 +3196,6 @@ js_InitStringClass(JSContext *cx, JSObject *obj) proto->brand(cx); ctor->brand(cx); - /* Install the fully-constructed String and String.prototype. */ if (!DefineConstructorAndPrototype(cx, global, JSProto_String, ctor, proto)) return NULL; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 3a4ab2976659..eaa34c2ace6b 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -202,6 +202,22 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx) return !v.isFalse(); } +JSFunction * +GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name, + uintN length) +{ + JSFunction *fun = js_NewFunction(cx, NULL, ctor, length, JSFUN_CONSTRUCTOR, this, name); + if (!fun) + return NULL; + + /* + * Remember the class this function is a constructor for so that we know to + * create an object of this class when we call the constructor. + */ + FUN_CLASP(fun) = clasp; + return fun; +} + JSObject * GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp) { diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 7f3d233cd6b4..f80db0dd3b2c 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -111,6 +111,13 @@ class GlobalObject : public ::JSObject { public: static GlobalObject *create(JSContext *cx, Class *clasp); + /* + * Create a constructor function with the specified name and length using + * ctor, a method which creates objects with the given class. + */ + JSFunction * + createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name, uintN length); + /* * Create an object to serve as [[Prototype]] for instances of the given * class, using |Object.prototype| as its [[Prototype]]. Users creating From 59836c24efdbf1ef4045bdd9ad4c8a3d9f7cc65e Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 15 Jun 2011 10:15:37 -0700 Subject: [PATCH 15/15] Bug 671091 - Add DefinePropertiesAndBrand to abstract out most explicit branding. NOT REVIEWED YET --HG-- extra : rebase_source : 9a48fc83a876c95e90c807eb0b007d35211eb41c --- js/src/jsobj.cpp | 17 +++-------------- js/src/jsregexp.cpp | 7 +------ js/src/jsstr.cpp | 9 ++------- js/src/vm/GlobalObject.cpp | 9 +++++++++ js/src/vm/GlobalObject.h | 7 +++++++ 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index f4f20cc7cb1a..cb55f3df719c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3838,23 +3838,12 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt ctor->setProto(proto); } - /* Add properties and methods to the prototype and the constructor. */ - if ((ps && !JS_DefineProperties(cx, proto, ps)) || - (fs && !JS_DefineFunctions(cx, proto, fs)) || - (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) || - (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) { + if (!DefinePropertiesAndBrand(cx, proto, ps, fs) || + (ctor != proto && !DefinePropertiesAndBrand(cx, ctor, static_ps, static_fs))) + { goto bad; } - /* - * Pre-brand the prototype and constructor if they have built-in methods. - * This avoids extra shape guard branch exits in the tracejitted code. - */ - if (fs) - proto->brand(cx); - if (ctor != proto && static_fs) - ctor->brand(cx); - /* * Make sure proto's emptyShape is available to be shared by objects of * this class. JSObject::emptyShape is a one-slot cache. If we omit this, diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 2adb41bdb75f..f9e3ef99df18 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -841,13 +841,8 @@ js_InitRegExpClass(JSContext *cx, JSObject *obj) if (!proto->initRegExp(cx, re.get())) return NULL; - /* - * Now add the standard methods to RegExp.prototype, and pre-brand for - * better shape-guarding code. - */ - if (!JS_DefineFunctions(cx, proto, regexp_methods)) + if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods)) return NULL; - proto->brand(cx); JSFunction *ctor = global->createConstructor(cx, regexp_construct, &js_RegExpClass, CLASS_ATOM(cx, RegExp), 2); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index e773894331a5..0077acb5219c 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3185,17 +3185,12 @@ js_InitStringClass(JSContext *cx, JSObject *obj) if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; - /* Add properties and methods to the prototype and the constructor. */ - if (!JS_DefineFunctions(cx, proto, string_methods) || - !JS_DefineFunctions(cx, ctor, string_static_methods)) + if (!DefinePropertiesAndBrand(cx, proto, NULL, string_methods) || + !DefinePropertiesAndBrand(cx, ctor, NULL, string_static_methods)) { return NULL; } - /* Pre-brand String and String.prototype for trace-jitted code. */ - proto->brand(cx); - ctor->brand(cx); - if (!DefineConstructorAndPrototype(cx, global, JSProto_String, ctor, proto)) return NULL; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index eaa34c2ace6b..ff5f90a48901 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -252,4 +252,13 @@ LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto) ObjectValue(*ctor), PropertyStub, StrictPropertyStub, 0); } +bool +DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, JSPropertySpec *ps, JSFunctionSpec *fs) +{ + if ((ps && !JS_DefineProperties(cx, obj, ps)) || (fs && !JS_DefineFunctions(cx, obj, fs))) + return false; + obj->brand(cx); + return true; +} + } // namespace js diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index f80db0dd3b2c..67dd5bd8dcdb 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -177,6 +177,13 @@ class GlobalObject : public ::JSObject { extern bool LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto); +/* + * Define properties, then functions, on the object, then brand for tracing + * benefits. + */ +extern bool +DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, JSPropertySpec *ps, JSFunctionSpec *fs); + } // namespace js js::GlobalObject *