relanding of bug 370952: fix the reflow functions in nsPresShell. r+sr=dbaron

This commit is contained in:
sharparrow1@yahoo.com 2007-04-25 08:49:55 -07:00
Родитель 5dd2c9e259
Коммит 2fe1b6664d
1 изменённых файлов: 176 добавлений и 316 удалений

Просмотреть файл

@ -1070,6 +1070,11 @@ protected:
void ClearReflowEventStatus();
void PostReflowEvent();
void DoReflow(nsIFrame* aFrame);
#ifdef DEBUG
void DoVerifyReflow();
#endif
friend class nsPresShellEventCB;
class ReflowEvent;
@ -2649,8 +2654,6 @@ PresShell::sPaintSuppressionCallback(nsITimer *aTimer, void* aPresShell)
NS_IMETHODIMP
PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
{
PRBool firstReflow = PR_FALSE;
NS_ASSERTION(mViewManager, "Must have view manager");
mViewManager->BeginUpdateViewBatch();
@ -2670,91 +2673,27 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
return NS_ERROR_NOT_AVAILABLE;
}
if (mPresContext) {
nsRect r(0, 0, aWidth, aHeight);
mPresContext->SetVisibleArea(r);
}
mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
if (rootFrame) {
// There isn't anything useful we can do if the initial reflow hasn't happened
if (!rootFrame)
return NS_OK;
{
// Kick off a top-down reflow
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("enter nsPresShell::ResizeReflow: %d,%d", aWidth, aHeight));
#ifdef NS_DEBUG
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
}
}
#endif
#ifdef DEBUG_kipp
nsPresShell_ReflowStackPointerTop = (char*) &aWidth;
#endif
nsRect bounds = mPresContext->GetVisibleArea();
nsSize maxSize(bounds.width, bounds.height);
nsHTMLReflowMetrics desiredSize;
nsReflowStatus status;
nsIRenderingContext* rcx = nsnull;
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
if (NS_FAILED(rv)) return rv;
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
// XXXldb Set mIsReflowing (and unset it later)?
nsHTMLReflowState reflowState(mPresContext, rootFrame, rcx, maxSize);
rootFrame->WillReflow(mPresContext);
nsContainerFrame::PositionFrameView(rootFrame);
rootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
rootFrame->SetSize(nsSize(desiredSize.width, desiredSize.height));
mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height));
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, rootFrame->GetView(),
&desiredSize.mOverflowArea);
rootFrame->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
#ifdef NS_DEBUG
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
DoReflow(rootFrame);
mPresContext->SetVisibleArea(nsRect(nsPoint(0, 0), rootFrame->GetSize()));
}
}
#endif
VERIFY_STYLE_TREE;
NS_IF_RELEASE(rcx);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow"));
// XXX if debugging then we should assert that the cache is empty
} else {
firstReflow = PR_TRUE;
#ifdef NOISY
printf("PresShell::ResizeReflow: null root frame\n");
#endif
}
DidCauseReflow();
// if the proper flag is set, VerifyReflow now
#ifdef NS_DEBUG
if (GetVerifyReflowEnable() && (VERIFY_REFLOW_DURING_RESIZE_REFLOW & gVerifyReflowFlags))
{
mInVerifyReflow = PR_TRUE;
/*PRBool ok = */VerifyIncrementalReflow();
mInVerifyReflow = PR_FALSE;
}
#endif
DidDoReflow();
mViewManager->EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
if (!firstReflow) {
//Set resize event timer
CreateResizeEventTimer();
}
return NS_OK; //XXX this needs to be real. MMP
}
@ -3123,100 +3062,22 @@ PresShell::CheckVisibility(nsIDOMNode *node, PRInt16 startOffset, PRInt16 EndOff
//end implementations nsISelectionController
static void UpdateViewProperties(nsPresContext* aPresContext, nsIViewManager* aVM,
nsIView* aView) {
nsIViewManager* thisVM = aView->GetViewManager();
if (thisVM != aVM) {
return;
}
nsIFrame* frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
if (frame) {
nsContainerFrame::SyncFrameViewProperties(aPresContext, frame, nsnull, aView);
}
for (nsIView* child = aView->GetFirstChild(); child;
child = child->GetNextSibling()) {
UpdateViewProperties(aPresContext, aVM, child);
}
}
NS_IMETHODIMP
PresShell::StyleChangeReflow()
{
WillCauseReflow();
WillDoReflow();
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (rootFrame) {
// Mark everything dirty
// At the moment at least, we don't have a root frame before the initial
// reflow; it's safe to just ignore the request in that case
if (!rootFrame)
return NS_OK;
if (!(rootFrame->GetStateBits() &
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
rootFrame->AddStateBits(NS_FRAME_IS_DIRTY);
FrameNeedsReflow(rootFrame, eStyleChange);
// Kick off a top-down reflow
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("enter nsPresShell::StyleChangeReflow"));
#ifdef NS_DEBUG
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
}
}
#endif
nsRect bounds = mPresContext->GetVisibleArea();
nsSize maxSize(bounds.width, bounds.height);
nsHTMLReflowMetrics desiredSize;
nsReflowStatus status;
nsIRenderingContext* rcx = nsnull;
nsresult rv=CreateRenderingContext(rootFrame, &rcx);
if (NS_FAILED(rv)) return rv;
AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Reflow);
// XXXldb Set mIsReflowing (and unset it later)?
nsHTMLReflowState reflowState(mPresContext, rootFrame, rcx, maxSize);
rootFrame->WillReflow(mPresContext);
nsContainerFrame::PositionFrameView(rootFrame);
rootFrame->Reflow(mPresContext, desiredSize, reflowState, status);
rootFrame->SetSize(nsSize(desiredSize.width, desiredSize.height));
mPresContext->SetVisibleArea(nsRect(0,0,desiredSize.width,desiredSize.height));
nsIView* view = rootFrame->GetView();
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, rootFrame, view,
&desiredSize.mOverflowArea);
rootFrame->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
#ifdef NS_DEBUG
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
}
}
#endif
VERIFY_STYLE_TREE;
NS_IF_RELEASE(rcx);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::StyleChangeReflow"));
// The following two calls are needed to make sure we reacquire any needed
// style structs that were cleared by the caller
// Update properties of all views to reflect style changes
UpdateViewProperties(mPresContext, mViewManager, view);
// Repaint everything just to be sure
mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
mDirtyRoots.AppendElement(rootFrame);
}
DidCauseReflow();
DidDoReflow();
return NS_OK; //XXX this needs to be real. MMP
return FrameNeedsReflow(rootFrame, eStyleChange);
}
nsIFrame*
@ -3454,11 +3315,6 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty)
}
}
// If we're in the middle of a drag, process it right away (needed for mac,
// might as well do it on all platforms just to keep the code paths the same).
// XXXbz but how does this actually "process it right away"?
// Isn't this more like "never process it"?
if ( !IsDragInProgress() )
PostReflowEvent();
return NS_OK;
@ -6246,6 +6102,116 @@ PresShell::DidDoReflow()
}
}
void
PresShell::DoReflow(nsIFrame* target)
{
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
nsCOMPtr<nsIRenderingContext> rcx;
// Always create the rendering context relative to the root frame during
// reflow; otherwise, it crashes on the mac (I'm not quite sure why)
nsresult rv = CreateRenderingContext(rootFrame, getter_AddRefs(rcx));
if (NS_FAILED(rv)) {
NS_NOTREACHED("CreateRenderingContext failure");
return;
}
target->WillReflow(mPresContext);
// If the target frame is the root of the frame hierarchy, then
// use all the available space. If it's simply a `reflow root',
// then use the target frame's size as the available space.
nsSize size;
if (target == rootFrame)
size = mPresContext->GetVisibleArea().Size();
else
size = target->GetSize();
NS_ASSERTION(!target->GetNextInFlow() && !target->GetPrevInFlow(),
"reflow roots should never split");
// Don't pass size directly to the reflow state, since a
// constrained height implies page/column breaking.
// Exception: the root frame always uses a constrained reflow
nsSize reflowSize;
if (target != rootFrame)
reflowSize = nsSize(size.width, NS_UNCONSTRAINEDSIZE);
else
reflowSize = size;
nsHTMLReflowState reflowState(mPresContext, target, rcx, reflowSize);
// fix the computed height
NS_ASSERTION(reflowState.mComputedMargin == nsMargin(0, 0, 0, 0),
"reflow state should not set margin for reflow roots");
reflowState.mComputedHeight =
size.height - reflowState.mComputedBorderPadding.TopBottom();
NS_ASSERTION(reflowState.ComputedWidth() ==
size.width -
reflowState.mComputedBorderPadding.LeftRight(),
"reflow state computed incorrect width");
nsReflowStatus status;
nsHTMLReflowMetrics desiredSize;
target->Reflow(mPresContext, desiredSize, reflowState, status);
// If an incremental reflow is initiated at a frame other than the
// root frame, then its desired size had better not change!
NS_ASSERTION(target == rootFrame ||
(desiredSize.width == size.width &&
desiredSize.height == size.height),
"non-root frame's desired size changed during an "
"incremental reflow");
NS_ASSERTION(desiredSize.mOverflowArea ==
nsRect(nsPoint(0, 0),
nsSize(desiredSize.width, desiredSize.height)),
"reflow roots must not have visible overflow");
NS_ASSERTION(status == NS_FRAME_COMPLETE,
"reflow roots should never split");
target->SetSize(nsSize(desiredSize.width, desiredSize.height));
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, target,
target->GetView(),
&desiredSize.mOverflowArea);
target->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
#ifdef DEBUG
void
PresShell::DoVerifyReflow()
{
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
}
}
if (GetVerifyReflowEnable()) {
// First synchronously render what we have so far so that we can
// see it.
nsIView* rootView;
mViewManager->GetRootView(rootView);
mViewManager->UpdateView(rootView, NS_VMREFRESH_IMMEDIATE);
FlushPendingNotifications(Flush_Layout);
mInVerifyReflow = PR_TRUE;
PRBool ok = VerifyIncrementalReflow();
mInVerifyReflow = PR_FALSE;
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
printf("ProcessReflowCommands: finished (%s)\n",
ok ? "ok" : "failed");
}
if (0 != mDirtyRoots.Count()) {
printf("XXX yikes! reflow commands queued during verify-reflow\n");
}
}
}
#endif
nsresult
PresShell::ProcessReflowCommands(PRBool aInterruptible)
{
@ -6253,20 +6219,11 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
MOZ_TIMER_START(mReflowWatch);
if (0 != mDirtyRoots.Count()) {
nsHTMLReflowMetrics desiredSize;
nsCOMPtr<nsIRenderingContext> rcx;
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
nsSize maxSize = rootFrame->GetSize();
nsresult rv=CreateRenderingContext(rootFrame, getter_AddRefs(rcx));
if (NS_FAILED(rv)) return rv;
#ifdef DEBUG
if (GetVerifyReflowEnable()) {
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
printf("ProcessReflowCommands: begin incremental reflow\n");
}
}
#endif
WillDoReflow();
@ -6302,66 +6259,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
continue;
}
nsIFrame* root = mPresContext->FrameManager()->GetRootFrame();
target->WillReflow(mPresContext);
nsContainerFrame::PositionFrameView(target);
// If the target frame is the root of the frame hierarchy, then
// use all the available space. If it's simply a `reflow root',
// then use the target frame's size as the available space.
nsSize size;
if (target == root)
size = maxSize;
else
size = target->GetSize();
NS_ASSERTION(!target->GetNextInFlow() && !target->GetPrevInFlow(),
"reflow roots should never split");
// Don't pass size directly to the reflow state, since a
// constrained height implies page/column breaking.
nsHTMLReflowState reflowState(mPresContext, target, rcx,
nsSize(size.width, NS_UNCONSTRAINEDSIZE));
// fix the computed height
NS_ASSERTION(reflowState.mComputedMargin == nsMargin(0, 0, 0, 0),
"reflow state should not set margin for reflow roots");
reflowState.mComputedHeight =
size.height - reflowState.mComputedBorderPadding.TopBottom();
NS_ASSERTION(reflowState.ComputedWidth() ==
size.width -
reflowState.mComputedBorderPadding.LeftRight(),
"reflow state computed incorrect width");
// except the viewport frame does want availableHeight set
if (target == root)
reflowState.availableHeight = size.height;
nsReflowStatus status;
target->Reflow(mPresContext, desiredSize, reflowState, status);
// If an incremental reflow is initiated at a frame other than the
// root frame, then its desired size had better not change!
NS_ASSERTION(target == root ||
(desiredSize.width == size.width &&
desiredSize.height == size.height),
"non-root frame's desired size changed during an "
"incremental reflow");
NS_ASSERTION(desiredSize.mOverflowArea ==
nsRect(nsPoint(0, 0),
nsSize(desiredSize.width, desiredSize.height)),
"reflow roots must not have visible overflow");
NS_ASSERTION(status == NS_FRAME_COMPLETE,
"reflow roots should never split");
target->SetSize(nsSize(desiredSize.width, desiredSize.height));
nsContainerFrame::SyncFrameViewAfterReflow(mPresContext, target,
target->GetView(),
&desiredSize.mOverflowArea);
target->DidReflow(mPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
DoReflow(target);
// Keep going until we're out of reflow commands, or we've run
// past our deadline.
@ -6379,42 +6277,16 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
if (mDirtyRoots.Count())
PostReflowEvent();
DidDoReflow();
#ifdef DEBUG
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (VERIFY_REFLOW_DUMP_COMMANDS & gVerifyReflowFlags) {
printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n", (void*)this);
}
if (nsIFrameDebug::GetVerifyTreeEnable()) {
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(rootFrame->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
frameDebug->VerifyTree();
}
}
if (GetVerifyReflowEnable()) {
// First synchronously render what we have so far so that we can
// see it.
nsIView* rootView;
mViewManager->GetRootView(rootView);
mViewManager->UpdateView(rootView, NS_VMREFRESH_IMMEDIATE);
mInVerifyReflow = PR_TRUE;
PRBool ok = VerifyIncrementalReflow();
mInVerifyReflow = PR_FALSE;
if (VERIFY_REFLOW_ALL & gVerifyReflowFlags) {
printf("ProcessReflowCommands: finished (%s)\n",
ok ? "ok" : "failed");
}
if (0 != mDirtyRoots.Count()) {
printf("XXX yikes! reflow commands queued during verify-reflow\n");
}
}
DoVerifyReflow();
#endif
DidDoReflow();
// If there are no more reflow commands in the queue, we'll want
// to unblock onload.
DoneRemovingDirtyRoots();
@ -6669,6 +6541,8 @@ LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg)
}
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
fprintf(stdout, " %p ", (void*)k1);
printf(" != ");
if (nsnull != k2) {
@ -6684,6 +6558,8 @@ LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg)
}
fputs(NS_LossyConvertUTF16toASCII(name).get(), stdout);
fprintf(stdout, " %p ", (void*)k2);
printf(" %s", aMsg);
}
@ -7019,32 +6895,17 @@ PresShell::VerifyIncrementalReflow()
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
printf("Building Verification Tree...\n");
}
// All the stuff we are creating that needs releasing
nsPresContext* cx;
nsIViewManager* vm;
nsIPresShell* sh;
// Create a presentation context to view the new frame tree
NS_IF_ADDREF(cx = new nsPresContext(mDocument,
mPresContext->IsPaginated() ?
nsCOMPtr<nsPresContext> cx =
new nsPresContext(mDocument, mPresContext->IsPaginated() ?
nsPresContext::eContext_PrintPreview :
nsPresContext::eContext_Galley));
if (!cx)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
if (container) {
cx->SetContainer(container);
nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
if (lh) {
cx->SetLinkHandler(lh);
}
}
nsPresContext::eContext_Galley);
NS_ENSURE_TRUE(cx, PR_FALSE);
nsIDeviceContext *dc = mPresContext->DeviceContext();
nsresult rv = cx->Init(dc);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
// Get our scrolling preference
nsIView* rootView;
@ -7052,22 +6913,20 @@ PresShell::VerifyIncrementalReflow()
void* nativeParentWidget = rootView->GetWidget()->GetNativeData(NS_NATIVE_WIDGET);
// Create a new view manager.
rv = CallCreateInstance(kViewManagerCID, &vm);
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to create view manager");
nsCOMPtr<nsIViewManager> vm = do_CreateInstance(kViewManagerCID);
NS_ENSURE_TRUE(vm, PR_FALSE);
rv = vm->Init(dc);
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to init view manager");
NS_ENSURE_SUCCESS(rv, PR_FALSE);
// Create a child window of the parent that is our "root view/window"
// Create a view
nsRect tbounds = mPresContext->GetVisibleArea();
nsIView* view = vm->CreateView(tbounds, nsnull);
NS_ASSERTION(view, "failed to create view");
if (!view)
return PR_FALSE;
NS_ENSURE_TRUE(view, PR_FALSE);
//now create the widget for the view
rv = view->CreateWidget(kWidgetCID, nsnull, nativeParentWidget, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create scroll view widget");
NS_ENSURE_SUCCESS(rv, PR_FALSE);
// Setup hierarchical relationship in view manager
vm->SetRootView(view);
@ -7081,13 +6940,19 @@ PresShell::VerifyIncrementalReflow()
// exact same style information that this document has.
nsAutoPtr<nsStyleSet> newSet;
rv = CloneStyleSet(mStyleSet, getter_Transfers(newSet));
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to clone style set");
rv = mDocument->CreateShell(cx, vm, newSet, &sh);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
nsCOMPtr<nsIPresShell> sh;
rv = mDocument->CreateShell(cx, vm, newSet, getter_AddRefs(sh));
NS_ENSURE_SUCCESS(rv, PR_FALSE);
newSet.forget();
// Note that after we create the shell, we must make sure to destroy it
sh->SetVerifyReflowEnable(PR_FALSE); // turn off verify reflow while we're reflowing the test frame tree
NS_ASSERTION(NS_SUCCEEDED (rv), "failed to create presentation shell");
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
rv = sh->InitialReflow(r.width, r.height);
NS_ENSURE_SUCCESS(rv, rv);
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh.get()));
WillCauseReflow();
sh->InitialReflow(r.width, r.height);
DidCauseReflow();
mDocument->BindingManager()->ProcessAttachedQueue();
sh->FlushPendingNotifications(Flush_Layout);
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
printf("Verification Tree built, comparing...\n");
@ -7102,22 +6967,17 @@ PresShell::VerifyIncrementalReflow()
printf("Verify reflow failed, primary tree:\n");
nsIFrameDebug* frameDebug;
if (NS_SUCCEEDED(root1->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
if (NS_SUCCEEDED(CallQueryInterface(root1, &frameDebug))) {
frameDebug->List(stdout, 0);
}
printf("Verification tree:\n");
if (NS_SUCCEEDED(root2->QueryInterface(NS_GET_IID(nsIFrameDebug),
(void**)&frameDebug))) {
if (NS_SUCCEEDED(CallQueryInterface(root2, &frameDebug))) {
frameDebug->List(stdout, 0);
}
}
cx->SetContainer(nsnull);
NS_RELEASE(cx);
sh->EndObservingDocument();
NS_RELEASE(sh);
NS_RELEASE(vm);
sh->Destroy();
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
printf("Finished Verifying Reflow...\n");
}