diff --git a/browser/components/migration/src/nsIEProfileMigrator.cpp b/browser/components/migration/src/nsIEProfileMigrator.cpp index 4b6798e6b40a..03582d00c6c8 100644 --- a/browser/components/migration/src/nsIEProfileMigrator.cpp +++ b/browser/components/migration/src/nsIEProfileMigrator.cpp @@ -1339,8 +1339,8 @@ nsIEProfileMigrator::CopyFavorites(bool aReplace) do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - bool batchAction = aReplace ? BATCH_ACTION_BOOKMARKS_REPLACE - : BATCH_ACTION_BOOKMARKS; + PRUint8 batchAction = aReplace ? BATCH_ACTION_BOOKMARKS_REPLACE + : BATCH_ACTION_BOOKMARKS; nsCOMPtr supports = do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID); NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY); diff --git a/build/automation.py.in b/build/automation.py.in index ae4a7574abcf..42a294681aae 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -418,10 +418,6 @@ user_pref("javascript.options.showInConsole", true); user_pref("devtools.errorconsole.enabled", true); user_pref("layout.debug.enable_data_xbl", true); user_pref("browser.EULA.override", true); -user_pref("javascript.options.tracejit.content", true); -user_pref("javascript.options.methodjit.content", true); -user_pref("javascript.options.jitprofiling.content", true); -user_pref("javascript.options.methodjit_always", false); user_pref("gfx.color_management.force_srgb", true); user_pref("network.manage-offline-status", false); user_pref("test.mousescroll", true); diff --git a/content/base/test/chrome/test_bug391728.html b/content/base/test/chrome/test_bug391728.html index 0fcad1e97f97..aa745105ed8c 100644 --- a/content/base/test/chrome/test_bug391728.html +++ b/content/base/test/chrome/test_bug391728.html @@ -6,7 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391728 Test for Bug 391728 - + diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index b381eb181df4..650deacecf42 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -527,14 +527,14 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height) height = 1; } - // If we already have a gl context, then we just need to resize - // FB0. - if (gl && - gl->ResizeOffscreen(gfxIntSize(width, height))) - { + // If we already have a gl context, then we just need to resize it + if (gl) { + gl->ResizeOffscreen(gfxIntSize(width, height)); // Doesn't matter if it succeeds (soft-fail) + // It's unlikely that we'll get a proper-sized context if we recreate if we didn't on resize + // everything's good, we're done here - mWidth = width; - mHeight = height; + mWidth = gl->OffscreenActualSize().width; + mHeight = gl->OffscreenActualSize().height; mResetLayer = true; return NS_OK; } @@ -601,6 +601,11 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height) format.minAlpha = 0; } + if (mOptions.antialias) { + PRUint32 msaaLevel = Preferences::GetUint("webgl.msaa-level", 2); + format.samples = msaaLevel*msaaLevel; + } + if (PR_GetEnv("MOZ_WEBGL_PREFER_EGL")) { preferEGL = true; } @@ -898,7 +903,7 @@ WebGLContext::GetContextAttributes(jsval *aResult) NULL, NULL, JSPROP_ENUMERATE) || !JS_DefineProperty(cx, obj, "stencil", cf.stencil > 0 ? JSVAL_TRUE : JSVAL_FALSE, NULL, NULL, JSPROP_ENUMERATE) || - !JS_DefineProperty(cx, obj, "antialias", JSVAL_FALSE, + !JS_DefineProperty(cx, obj, "antialias", cf.samples > 0 ? JSVAL_TRUE : JSVAL_FALSE, NULL, NULL, JSPROP_ENUMERATE) || !JS_DefineProperty(cx, obj, "premultipliedAlpha", mOptions.premultipliedAlpha ? JSVAL_TRUE : JSVAL_FALSE, diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index b5915f0747d0..71ea08c2a96f 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -310,7 +310,7 @@ struct WebGLContextOptions { // these are defaults WebGLContextOptions() : alpha(true), depth(true), stencil(false), - premultipliedAlpha(true), antialias(false), + premultipliedAlpha(true), antialias(true), preserveDrawingBuffer(false) { } diff --git a/content/canvas/test/webgl/failing_tests_linux.txt b/content/canvas/test/webgl/failing_tests_linux.txt index 0e3a11e44b02..045968571711 100644 --- a/content/canvas/test/webgl/failing_tests_linux.txt +++ b/content/canvas/test/webgl/failing_tests_linux.txt @@ -1,5 +1,3 @@ -conformance/canvas/drawingbuffer-static-canvas-test.html -conformance/canvas/drawingbuffer-test.html conformance/context/premultiplyalpha-test.html conformance/glsl/misc/glsl-long-variable-names.html conformance/glsl/misc/shader-with-256-character-identifier.frag.html @@ -8,7 +6,6 @@ conformance/misc/uninitialized-test.html conformance/programs/gl-get-active-attribute.html conformance/reading/read-pixels-test.html conformance/renderbuffers/framebuffer-object-attachment.html -conformance/renderbuffers/renderbuffer-initialization.html conformance/textures/texture-mips.html conformance/uniforms/gl-uniform-bool.html conformance/more/functions/copyTexImage2D.html diff --git a/content/canvas/test/webgl/failing_tests_mac.txt b/content/canvas/test/webgl/failing_tests_mac.txt index 83fbd3f0ba21..b8d84f636952 100644 --- a/content/canvas/test/webgl/failing_tests_mac.txt +++ b/content/canvas/test/webgl/failing_tests_mac.txt @@ -1,6 +1,4 @@ conformance/canvas/buffer-preserve-test.html -conformance/canvas/drawingbuffer-static-canvas-test.html -conformance/canvas/drawingbuffer-test.html conformance/context/context-attributes-alpha-depth-stencil-antialias.html conformance/context/premultiplyalpha-test.html conformance/glsl/misc/glsl-function-nodes.html diff --git a/content/canvas/test/webgl/failing_tests_windows.txt b/content/canvas/test/webgl/failing_tests_windows.txt index 81d0e98729ff..863b9fa2e49e 100644 --- a/content/canvas/test/webgl/failing_tests_windows.txt +++ b/content/canvas/test/webgl/failing_tests_windows.txt @@ -1,6 +1,4 @@ conformance/canvas/buffer-preserve-test.html -conformance/canvas/drawingbuffer-static-canvas-test.html -conformance/canvas/drawingbuffer-test.html conformance/context/premultiplyalpha-test.html conformance/glsl/functions/glsl-function-atan.html conformance/glsl/functions/glsl-function-atan-xy.html diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 5c9d935ae1f5..4132825c63d3 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -1675,7 +1675,8 @@ nsEventStateManager::DispatchCrossProcessEvent(nsEvent* aEvent, nsIFrameLoader* bool nsEventStateManager::IsRemoteTarget(nsIContent* target) { return target && - target->Tag() == nsGkAtoms::browser && + (target->Tag() == nsGkAtoms::browser || + target->Tag() == nsGkAtoms::iframe) && target->IsXUL() && target->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote, nsGkAtoms::_true, eIgnoreCase); diff --git a/content/media/VideoUtils.h b/content/media/VideoUtils.h index 9791cb3330b7..1b6f41738338 100644 --- a/content/media/VideoUtils.h +++ b/content/media/VideoUtils.h @@ -166,4 +166,10 @@ void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio); #define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE #endif +// Android's audio backend is not available in content processes, so audio must +// be remoted to the parent chrome process. +#if defined(ANDROID) +#define REMOTE_AUDIO 1 +#endif + #endif diff --git a/content/media/nsAudioStream.cpp b/content/media/nsAudioStream.cpp index 2f3e2c204aed..3ee4bf248f16 100644 --- a/content/media/nsAudioStream.cpp +++ b/content/media/nsAudioStream.cpp @@ -66,12 +66,6 @@ using namespace mozilla; #define SA_PER_STREAM_VOLUME 1 #endif -// Android's audio backend is not available in content processes, so audio must -// be remoted to the parent chrome process. -#if defined(ANDROID) -#define REMOTE_AUDIO 1 -#endif - using mozilla::TimeStamp; #ifdef PR_LOGGING @@ -80,6 +74,9 @@ PRLogModuleInfo* gAudioStreamLog = nsnull; static const PRUint32 FAKE_BUFFER_SIZE = 176400; +// Number of milliseconds per second. +static const PRInt64 MS_PER_S = 1000; + class nsNativeAudioStream : public nsAudioStream { public: @@ -752,9 +749,9 @@ nsRemotedAudioStream::GetPositionInFrames() return 0; PRInt64 time = mAudioChild->GetLastKnownPositionTimestamp(); - PRInt64 result = position + (mRate * (PR_IntervalNow() - time) / USECS_PER_S); + PRInt64 dt = PR_IntervalToMilliseconds(PR_IntervalNow() - time); - return result; + return position + (mRate * dt / MS_PER_S); } bool diff --git a/content/media/nsBuiltinDecoderStateMachine.cpp b/content/media/nsBuiltinDecoderStateMachine.cpp index aef55f61e196..3e0cec3710a4 100644 --- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -635,6 +635,29 @@ void nsBuiltinDecoderStateMachine::AudioLoop() NS_WARNING("Int overflow calculating audio end time"); break; } + +// The remoted audio stream does not block writes when the other end's buffers +// are full, so this sleep is necessary to stop the audio thread spinning its +// wheels. When bug 695612 is fixed, this block of code can be removed. +#if defined(REMOTE_AUDIO) + PRInt64 audioAhead = mAudioEndTime - GetMediaTime(); + if (audioAhead > AMPLE_AUDIO_USECS && + framesWritten > minWriteFrames) + { + // We've pushed enough audio onto the hardware that we've queued up a + // significant amount ahead of the playback position. The decode + // thread will be going to sleep, so we won't get any new audio + // anyway, so sleep until we need to push to the hardware again. + Wait(AMPLE_AUDIO_USECS / 2); + // Kick the decode thread; since above we only do a NotifyAll when + // we pop an audio chunk of the queue, the decoder won't wake up if + // we've got no more decoded chunks to push to the hardware. We can + // hit this condition if the last frame in the stream doesn't have + // it's EOS flag set, and the decode thread sleeps just after decoding + // that packet, but before realising there's no more packets. + mon.NotifyAll(); + } +#endif } } if (mReader->mAudioQueue.AtEndOfStream() && diff --git a/content/svg/content/src/nsSVGImageElement.cpp b/content/svg/content/src/nsSVGImageElement.cpp index 9fefc872c709..b097bdeb722d 100644 --- a/content/svg/content/src/nsSVGImageElement.cpp +++ b/content/svg/content/src/nsSVGImageElement.cpp @@ -45,7 +45,6 @@ #include "imgIContainer.h" #include "imgIDecoderObserver.h" #include "gfxContext.h" -#include "mozilla/Preferences.h" using namespace mozilla; @@ -168,28 +167,6 @@ nsSVGImageElement::LoadSVGImage(bool aForce, bool aNotify) //---------------------------------------------------------------------- // nsIContent methods: -nsresult -nsSVGImageElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, - const nsAString* aValue, bool aNotify) -{ - if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) { - // If caller is not chrome and dom.disable_image_src_set is true, - // prevent setting image.src by exiting early - if (Preferences::GetBool("dom.disable_image_src_set") && - !nsContentUtils::IsCallerChrome()) { - return NS_OK; - } - - if (aValue) { - LoadSVGImage(true, aNotify); - } else { - CancelImageRequests(aNotify); - } - } - return nsSVGImageElementBase::AfterSetAttr(aNamespaceID, aName, - aValue, aNotify); -} - void nsSVGImageElement::MaybeLoadSVGImage() { @@ -281,17 +258,6 @@ nsSVGImageElement::GetStringInfo() ArrayLength(sStringInfo)); } -void -nsSVGImageElement::DidAnimateString(PRUint8 aAttrEnum) -{ - if (aAttrEnum == HREF) { - LoadSVGImage(true, false); - return; - } - - nsSVGImageElementBase::DidAnimateString(aAttrEnum); -} - nsresult nsSVGImageElement::CopyInnerTo(nsGenericElement* aDest) const { diff --git a/content/svg/content/src/nsSVGImageElement.h b/content/svg/content/src/nsSVGImageElement.h index 3e59da4949c3..8893bf519650 100644 --- a/content/svg/content/src/nsSVGImageElement.h +++ b/content/svg/content/src/nsSVGImageElement.h @@ -77,8 +77,6 @@ public: NS_FORWARD_NSIDOMSVGELEMENT(nsSVGImageElementBase::) // nsIContent interface - virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, - const nsAString* aValue, bool aNotify); virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); @@ -103,7 +101,6 @@ protected: virtual LengthAttributesInfo GetLengthInfo(); virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio(); virtual StringAttributesInfo GetStringInfo(); - virtual void DidAnimateString(PRUint8 aAttrEnum); enum { X, Y, WIDTH, HEIGHT }; nsSVGLength2 mLengthAttributes[4]; diff --git a/docshell/test/chrome/docshell_helpers.js b/docshell/test/chrome/docshell_helpers.js index 0c078efa6871..29ac35fce897 100755 --- a/docshell/test/chrome/docshell_helpers.js +++ b/docshell/test/chrome/docshell_helpers.js @@ -342,7 +342,6 @@ function finish() { // If the test changed the value of max_total_viewers via a call to // enableBFCache(), then restore it now. if (typeof(gOrigMaxTotalViewers) != "undefined") { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); prefs.setIntPref("browser.sessionhistory.max_total_viewers", @@ -425,7 +424,6 @@ function waitForTrue(fn, onWaitComplete, timeout) { * to 0 (disabled), if a number, set it to that specific number */ function enableBFCache(enable) { - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 49f1205e8d4b..c60503a02eca 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -2980,7 +2980,8 @@ nsFocusManager::GetRootForFocus(nsPIDOMWindow* aWindow, TabParent* nsFocusManager::GetRemoteForContent(nsIContent* aContent) { if (!aContent || - aContent->Tag() != nsGkAtoms::browser || + (aContent->Tag() != nsGkAtoms::browser && + aContent->Tag() != nsGkAtoms::iframe) || !aContent->IsXUL() || !aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote, nsGkAtoms::_true, eIgnoreCase)) diff --git a/dom/ipc/CrashReporterParent.h b/dom/ipc/CrashReporterParent.h index 9693cca9c3c6..07c5f39570d1 100644 --- a/dom/ipc/CrashReporterParent.h +++ b/dom/ipc/CrashReporterParent.h @@ -86,7 +86,7 @@ public: the protocol. */ template - static void CreateCrashReporter(Toplevel* actor); + static bool CreateCrashReporter(Toplevel* actor); #endif /* Initialize this reporter with data from the child process */ void @@ -176,7 +176,7 @@ CrashReporterParent::GenerateCrashReport(Toplevel* t, } template -/* static */ void +/* static */ bool CrashReporterParent::CreateCrashReporter(Toplevel* actor) { #ifdef MOZ_CRASHREPORTER @@ -189,7 +189,9 @@ CrashReporterParent::CreateCrashReporter(Toplevel* actor) } else { NS_ERROR("Error creating crash reporter actor"); } + return !!p; #endif + return false; } #endif diff --git a/dom/plugins/base/android/ANPSurface.cpp b/dom/plugins/base/android/ANPSurface.cpp index f4984b1d286e..54f327d63d1a 100644 --- a/dom/plugins/base/android/ANPSurface.cpp +++ b/dom/plugins/base/android/ANPSurface.cpp @@ -42,6 +42,7 @@ #include "AndroidBridge.h" #include "gfxImageSurface.h" #include "gfxContext.h" +#include "nsNPAPIPluginInstance.h" #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) #define ASSIGN(obj, name) (obj)->name = anp_surface_##name @@ -51,17 +52,11 @@ static struct ANPSurfaceInterfaceJavaGlue { bool initialized; jclass geckoAppShellClass; - jclass lockInfoCls; - jmethodID lockSurfaceANP; - jmethodID jUnlockSurfaceANP; - jfieldID jDirtyTop; - jfieldID jDirtyLeft; - jfieldID jDirtyBottom; - jfieldID jDirtyRight; + jclass surfaceInfoCls; + jmethodID getSurfaceInfo; jfieldID jFormat; jfieldID jWidth ; jfieldID jHeight; - jfieldID jBuffer; } gSurfaceJavaGlue; #define getClassGlobalRef(env, cname) \ @@ -74,23 +69,16 @@ static void init(JNIEnv* env) { gSurfaceJavaGlue.geckoAppShellClass = mozilla::AndroidBridge::GetGeckoAppShellClass(); jmethodID getClass = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, - "getSurfaceLockInfoClass", + "getSurfaceInfoClass", "()Ljava/lang/Class;"); - gSurfaceJavaGlue.lockInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass)); + gSurfaceJavaGlue.surfaceInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass)); - gSurfaceJavaGlue.jDirtyTop = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyTop", "I"); - gSurfaceJavaGlue.jDirtyLeft = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyLeft", "I"); - gSurfaceJavaGlue.jDirtyBottom = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyBottom", "I"); - gSurfaceJavaGlue.jDirtyRight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyRight", "I"); + gSurfaceJavaGlue.jFormat = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "format", "I"); + gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "width", "I"); + gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "height", "I"); - gSurfaceJavaGlue.jFormat = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "format", "I"); - gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "width", "I"); - gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "height", "I"); - - gSurfaceJavaGlue.jBuffer = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "buffer", "Ljava/nio/Buffer;"); - gSurfaceJavaGlue.lockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "lockSurfaceANP", "(Landroid/view/SurfaceView;IIII)Lorg/mozilla/gecko/SurfaceLockInfo;"); - gSurfaceJavaGlue.jUnlockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "unlockSurfaceANP", "(Landroid/view/SurfaceView;)V"); + gSurfaceJavaGlue.getSurfaceInfo = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "getSurfaceInfo", "(Landroid/view/SurfaceView;)Lorg/mozilla/gecko/SurfaceInfo;"); gSurfaceJavaGlue.initialized = true; } @@ -103,62 +91,68 @@ static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRec init(env); - jvalue args[5]; - args[0].l = surfaceView; - if (dirtyRect) { - args[1].i = dirtyRect->top; - args[2].i = dirtyRect->left; - args[3].i = dirtyRect->bottom; - args[4].i = dirtyRect->right; - LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right); - } else { - args[1].i = args[2].i = args[3].i = args[4].i = 0; - } - jobject info = env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, - gSurfaceJavaGlue.lockSurfaceANP, - surfaceView, args[1].i, args[2].i, args[3].i, args[4].i); + gSurfaceJavaGlue.getSurfaceInfo, surfaceView); LOG("info: %p", info); if (!info) return false; - // the surface may have expanded the dirty region so we must to pass that - // information back to the plugin. - if (dirtyRect) { - dirtyRect->left = env->GetIntField(info, gSurfaceJavaGlue.jDirtyLeft); - dirtyRect->right = env->GetIntField(info, gSurfaceJavaGlue.jDirtyRight); - dirtyRect->top = env->GetIntField(info, gSurfaceJavaGlue.jDirtyTop); - dirtyRect->bottom = env->GetIntField(info, gSurfaceJavaGlue.jDirtyBottom); - LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right); - } - bitmap->width = env->GetIntField(info, gSurfaceJavaGlue.jWidth); bitmap->height = env->GetIntField(info, gSurfaceJavaGlue.jHeight); + if (bitmap->width <= 0 || bitmap->height <= 0) + return false; + int format = env->GetIntField(info, gSurfaceJavaGlue.jFormat); + gfxImageFormat targetFormat; // format is PixelFormat if (format & 0x00000001) { + /* bitmap->format = kRGBA_8888_ANPBitmapFormat; bitmap->rowBytes = bitmap->width * 4; - } - else if (format & 0x00000004) { + targetFormat = gfxASurface::ImageFormatARGB32; + */ + + // We actually can't handle this right now because gfxImageSurface + // doesn't support RGBA32. + LOG("Unable to handle 32bit pixel format"); + return false; + } else if (format & 0x00000004) { bitmap->format = kRGB_565_ANPBitmapFormat; bitmap->rowBytes = bitmap->width * 2; - } - else { + targetFormat = gfxASurface::ImageFormatRGB16_565; + } else { LOG("format from glue is unknown %d\n", format); return false; } - jobject buf = env->GetObjectField(info, gSurfaceJavaGlue.jBuffer); - bitmap->baseAddr = env->GetDirectBufferAddress(buf); + nsNPAPIPluginInstance* pinst = nsNPAPIPluginInstance::FindByJavaSurface((void*)surfaceView); + if (!pinst) { + LOG("Failed to get plugin instance"); + return false; + } + + NPRect lockRect; + if (dirtyRect) { + lockRect.top = dirtyRect->top; + lockRect.left = dirtyRect->left; + lockRect.right = dirtyRect->right; + lockRect.bottom = dirtyRect->bottom; + } else { + // No dirty rect, use the whole bitmap + lockRect.top = lockRect.left = 0; + lockRect.right = bitmap->width; + lockRect.bottom = bitmap->height; + } - LOG("format: %d, width: %d, height: %d", bitmap->format, bitmap->width, bitmap->height); + gfxImageSurface* target = pinst->LockTargetSurface(bitmap->width, bitmap->height, targetFormat, &lockRect); + bitmap->baseAddr = target->Data(); + env->DeleteLocalRef(info); - env->DeleteLocalRef(buf); - return ( bitmap->width > 0 && bitmap->height > 0 ); + + return true; } static void anp_unlock(JNIEnv* env, jobject surfaceView) { @@ -169,10 +163,13 @@ static void anp_unlock(JNIEnv* env, jobject surfaceView) { return; } - init(env); - env->CallStaticVoidMethod(gSurfaceJavaGlue.geckoAppShellClass, gSurfaceJavaGlue.jUnlockSurfaceANP, surfaceView); - LOG("returning from %s", __PRETTY_FUNCTION__); - + nsNPAPIPluginInstance* pinst = nsNPAPIPluginInstance::FindByJavaSurface((void*)surfaceView); + if (!pinst) { + LOG("Could not find plugin instance!"); + return; + } + + pinst->UnlockTargetSurface(true /* invalidate the locked area */); } /////////////////////////////////////////////////////////////////////////////// diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index 1df6125f47f4..2520d60db4b1 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -578,6 +578,29 @@ nsNPAPIPlugin::Shutdown() return NS_OK; } +nsresult +nsNPAPIPlugin::RetainStream(NPStream *pstream, nsISupports **aRetainedPeer) +{ + if (!aRetainedPeer) + return NS_ERROR_NULL_POINTER; + + *aRetainedPeer = NULL; + + if (!pstream || !pstream->ndata) + return NPERR_INVALID_PARAM; + + nsNPAPIPluginStreamListener* listener = + static_cast(pstream->ndata); + nsPluginStreamListenerPeer* peer = listener->GetStreamListenerPeer(); + + if (!peer) + return NPERR_GENERIC_ERROR; + + *aRetainedPeer = (nsISupports*) peer; + NS_ADDREF(*aRetainedPeer); + return NS_OK; +} + // Create a new NPP GET or POST (given in the type argument) url // stream that may have a notify callback NPError diff --git a/dom/plugins/base/nsNPAPIPlugin.h b/dom/plugins/base/nsNPAPIPlugin.h index b8d0a168a78c..df95b45dd931 100644 --- a/dom/plugins/base/nsNPAPIPlugin.h +++ b/dom/plugins/base/nsNPAPIPlugin.h @@ -106,6 +106,8 @@ public: nsresult CreatePluginInstance(nsNPAPIPluginInstance **aResult); nsresult Shutdown(); + static nsresult RetainStream(NPStream *pstream, nsISupports **aRetainedPeer); + protected: NPPluginFuncs mPluginFuncs; PluginLibrary* mLibrary; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index ca6c5298ee30..3e990d6f78a5 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -65,7 +65,6 @@ #include "ANPBase.h" #include #include "android_npapi.h" -#include "mozilla/Mutex.h" #include "mozilla/CondVar.h" #include "AndroidBridge.h" #endif @@ -73,6 +72,11 @@ using namespace mozilla; using namespace mozilla::plugins::parent; +#ifdef ANDROID +#include +static std::map sSurfaceMap; +#endif + static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID); static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID); @@ -89,6 +93,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) #endif #ifdef ANDROID mSurface(nsnull), + mTargetSurface(nsnull), mDrawingModel(0), #endif mRunning(NOT_STARTED), @@ -122,6 +127,10 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) mUsePluginLayersPref = useLayersPref; } +#ifdef ANDROID + mTargetSurfaceLock = new Mutex("nsNPAPIPluginInstance::SurfaceLock"); +#endif + PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this)); } @@ -133,6 +142,22 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance() PR_Free((void *)mMIMEType); mMIMEType = nsnull; } + +#ifdef ANDROID + if (mSurface) { + sSurfaceMap.erase(mSurface); + } + + if (mTargetSurface) { + delete mTargetSurface; + mTargetSurface = nsnull; + } + + if (mTargetSurfaceLock) { + delete mTargetSurfaceLock; + mTargetSurfaceLock = nsnull; + } +#endif } void @@ -338,7 +363,12 @@ nsNPAPIPluginInstance::InitializePlugin() const char* const* pnames = nsnull; const char* const* pvalues = nsnull; if (NS_SUCCEEDED(GetParameters(pcount, pnames, pvalues))) { + // Android expects an empty string as the separator instead of null +#ifdef ANDROID + NS_ASSERTION(PL_strcmp(values[count], "") == 0, "attribute/parameter array not setup correctly for Android NPAPI plugins"); +#else NS_ASSERTION(!values[count], "attribute/parameter array not setup correctly for NPAPI plugins"); +#endif if (pcount) count += ++pcount; // if it's all setup correctly, then all we need is to // change the count (attrs + PARAM/blank + params) @@ -770,9 +800,61 @@ void* nsNPAPIPluginInstance::GetJavaSurface() nsCOMPtr sg = new SurfaceGetter(mPlugin->PluginFuncs(), mNPP); mSurface = sg->GetSurface(); + sSurfaceMap[mSurface] = this; return mSurface; } +gfxImageSurface* +nsNPAPIPluginInstance::LockTargetSurface() +{ + mTargetSurfaceLock->Lock(); + return mTargetSurface; +} + +gfxImageSurface* +nsNPAPIPluginInstance::LockTargetSurface(PRUint32 aWidth, PRUint32 aHeight, gfxImageFormat aFormat, + NPRect* aRect) +{ + mTargetSurfaceLock->Lock(); + if (!mTargetSurface || + mTargetSurface->Width() != aWidth || + mTargetSurface->Height() != aHeight || + mTargetSurface->Format() != aFormat) { + + if (mTargetSurface) { + delete mTargetSurface; + } + + mTargetSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight), aFormat); + } + + mTargetLockRect = *aRect; + + return mTargetSurface; +} + +void +nsNPAPIPluginInstance::InvalidateTargetRect() +{ + InvalidateRect(&mTargetLockRect); +} + +void +nsNPAPIPluginInstance::UnlockTargetSurface(bool aInvalidate) +{ + mTargetSurfaceLock->Unlock(); + + if (aInvalidate) { + NS_DispatchToMainThread(NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::InvalidateTargetRect)); + } +} + +nsNPAPIPluginInstance* +nsNPAPIPluginInstance::FindByJavaSurface(void* aJavaSurface) +{ + return sSurfaceMap[aJavaSurface]; +} + #endif nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel) diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 8f868174302d..e2fd1e217431 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -50,9 +50,16 @@ #include "nsInterfaceHashtable.h" #include "nsHashKeys.h" +#include "gfxASurface.h" +#include "gfxImageSurface.h" + #include "mozilla/TimeStamp.h" #include "mozilla/PluginLibrary.h" +#ifdef ANDROID +#include "mozilla/Mutex.h" +#endif + struct JSObject; class nsPluginStreamListenerPeer; // browser-initiated stream class @@ -148,6 +155,13 @@ public: #ifdef ANDROID void SetDrawingModel(PRUint32 aModel); void* GetJavaSurface(); + + gfxImageSurface* LockTargetSurface(); + gfxImageSurface* LockTargetSurface(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat, + NPRect* aRect); + void UnlockTargetSurface(bool aInvalidate); + + static nsNPAPIPluginInstance* FindByJavaSurface(void* aJavaSurface); #endif nsresult NewStreamListener(const char* aURL, void* notifyData, @@ -264,7 +278,12 @@ private: bool mUsePluginLayersPref; #ifdef ANDROID + void InvalidateTargetRect(); + void* mSurface; + gfxImageSurface *mTargetSurface; + mozilla::Mutex* mTargetSurfaceLock; + NPRect mTargetLockRect; #endif }; diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index c9089a66d88f..757ecbfe3484 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1233,12 +1233,9 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays() // Set to the next slot to fill in name and value cache arrays. PRUint32 nextAttrParamIndex = 0; - // Potentially add WMODE attribute. - if (!wmodeType.IsEmpty()) { - mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode")); - mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType)); - nextAttrParamIndex++; - } + // Whether or not we force the wmode below while traversing + // the name/value pairs. + bool wmodeSet = false; // Add attribute name/value pairs. for (PRInt32 index = start; index != end; index += increment) { @@ -1252,7 +1249,25 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays() FixUpURLS(name, value); mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(name); - mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value); + if (!wmodeType.IsEmpty() && + 0 == PL_strcasecmp(mCachedAttrParamNames[nextAttrParamIndex], "wmode")) { + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType)); + + if (!wmodeSet) { + // We allocated space to add a wmode attr, but we don't need it now. + mNumCachedAttrs--; + wmodeSet = true; + } + } else { + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(value); + } + nextAttrParamIndex++; + } + + // Potentially add WMODE attribute. + if (!wmodeType.IsEmpty() && !wmodeSet) { + mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("wmode")); + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType)); nextAttrParamIndex++; } @@ -1656,6 +1671,27 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY) } #ifdef ANDROID +void nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect) +{ + void* javaSurface = mInstance->GetJavaSurface(); + + if (!javaSurface) + return; + + JNIEnv* env = GetJNIForThread(); + jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); + jmethodID method = env->GetStaticMethodID(cls, + "addPluginView", + "(Landroid/view/View;DDDD)V"); + env->CallStaticVoidMethod(cls, + method, + javaSurface, + aRect.x, + aRect.y, + aRect.width, + aRect.height); +} + void nsPluginInstanceOwner::RemovePluginView() { if (mInstance && mObjectFrame) { @@ -2797,45 +2833,6 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS) #ifdef ANDROID -class AndroidPaintEventRunnable : public nsRunnable -{ -public: - AndroidPaintEventRunnable(void* aSurface, nsNPAPIPluginInstance* inst, const gfxRect& aFrameRect) - : mSurface(aSurface), mInstance(inst), mFrameRect(aFrameRect) { - } - - ~AndroidPaintEventRunnable() { - } - - NS_IMETHOD Run() - { - LOG("%p - AndroidPaintEventRunnable::Run\n", this); - - if (!mInstance || !mSurface) - return NS_OK; - - // This needs to happen on the gecko main thread. - JNIEnv* env = GetJNIForThread(); - jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); - jmethodID method = env->GetStaticMethodID(cls, - "addPluginView", - "(Landroid/view/View;DDDD)V"); - env->CallStaticVoidMethod(cls, - method, - mSurface, - mFrameRect.x, - mFrameRect.y, - mFrameRect.width, - mFrameRect.height); - return NS_OK; - } -private: - void* mSurface; - nsCOMPtr mInstance; - gfxRect mFrameRect; -}; - - void nsPluginInstanceOwner::Paint(gfxContext* aContext, const gfxRect& aFrameRect, const gfxRect& aDirtyRect) @@ -2847,33 +2844,20 @@ void nsPluginInstanceOwner::Paint(gfxContext* aContext, mInstance->GetDrawingModel(&model); if (model == kSurface_ANPDrawingModel) { + AddPluginView(aFrameRect); - { - ANPEvent event; - event.inSize = sizeof(ANPEvent); - event.eventType = kLifecycle_ANPEventType; - event.data.lifecycle.action = kOnScreen_ANPLifecycleAction; - mInstance->HandleEvent(&event, nsnull); + gfxImageSurface* pluginSurface = mInstance->LockTargetSurface(); + if (!pluginSurface) { + mInstance->UnlockTargetSurface(false); + return; } - /* - gfxMatrix currentMatrix = aContext->CurrentMatrix(); - gfxSize scale = currentMatrix.ScaleFactors(true); - printf_stderr("!!!!!!!! scale!!: %f x %f\n", scale.width, scale.height); - */ + aContext->SetOperator(gfxContext::OPERATOR_SOURCE); + aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y)); + aContext->Clip(aDirtyRect); + aContext->Paint(); - JNIEnv* env = GetJNIForThread(); - jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); - jmethodID method = env->GetStaticMethodID(cls, - "addPluginView", - "(Landroid/view/View;DDDD)V"); - env->CallStaticVoidMethod(cls, - method, - mInstance->GetJavaSurface(), - aFrameRect.x, - aFrameRect.y, - aFrameRect.width, - aFrameRect.height); + mInstance->UnlockTargetSurface(false); return; } diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index 8b2457a46f8a..bb5ac0be1a5c 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -309,6 +309,7 @@ private: void FixUpURLS(const nsString &name, nsAString &value); #ifdef ANDROID + void AddPluginView(const gfxRect& aRect); void RemovePluginView(); #endif diff --git a/dom/plugins/ipc/BrowserStreamChild.cpp b/dom/plugins/ipc/BrowserStreamChild.cpp index 9154dfcc2739..201e7a5745ac 100644 --- a/dom/plugins/ipc/BrowserStreamChild.cpp +++ b/dom/plugins/ipc/BrowserStreamChild.cpp @@ -56,6 +56,7 @@ BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance, , mStreamStatus(kStreamOpen) , mDestroyPending(NOT_DESTROYED) , mNotifyPending(false) + , mStreamAsFilePending(false) , mInstanceDying(false) , mState(CONSTRUCTING) , mURL(url) @@ -140,7 +141,7 @@ BrowserStreamChild::RecvWrite(const int32_t& offset, } bool -BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname) +BrowserStreamChild::RecvNPP_StreamAsFile(const nsCString& fname) { PLUGIN_LOG_DEBUG(("%s (fname=%s)", FULLFUNCTION, fname.get())); @@ -152,8 +153,10 @@ BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname) if (kStreamOpen != mStreamStatus) return true; - mInstance->mPluginIface->asfile(&mInstance->mData, &mStream, - fname.get()); + mStreamAsFilePending = true; + mStreamAsFileName = fname; + EnsureDeliveryPending(); + return true; } @@ -238,6 +241,19 @@ BrowserStreamChild::Deliver() "Exit out of the data-delivery loop with pending data"); mPendingData.Clear(); + // NPP_StreamAsFile() is documented (at MDN) to be called "when the stream + // is complete" -- i.e. after all calls to NPP_WriteReady() and NPP_Write() + // have finished. We make these calls asynchronously (from + // DeliverPendingData()). So we need to make sure all the "pending data" + // has been "delivered" before calling NPP_StreamAsFile() (also + // asynchronously). Doing this resolves bug 687610, bug 670036 and possibly + // also other bugs. + if (mStreamAsFilePending) { + mInstance->mPluginIface->asfile(&mInstance->mData, &mStream, + mStreamAsFileName.get()); + mStreamAsFilePending = false; + } + if (DESTROY_PENDING == mDestroyPending) { mDestroyPending = DESTROYED; if (mState != DYING) diff --git a/dom/plugins/ipc/BrowserStreamChild.h b/dom/plugins/ipc/BrowserStreamChild.h index 9903acffd0ad..9a2a05fcf6f7 100644 --- a/dom/plugins/ipc/BrowserStreamChild.h +++ b/dom/plugins/ipc/BrowserStreamChild.h @@ -72,7 +72,7 @@ public: virtual bool RecvWrite(const int32_t& offset, const Buffer& data, const uint32_t& newsize); - virtual bool AnswerNPP_StreamAsFile(const nsCString& fname); + virtual bool RecvNPP_StreamAsFile(const nsCString& fname); virtual bool RecvNPP_DestroyStream(const NPReason& reason); virtual bool Recv__delete__(); @@ -166,6 +166,8 @@ private: DESTROYED // NPP_DestroyStream delivered, NPP_URLNotify may still be pending } mDestroyPending; bool mNotifyPending; + bool mStreamAsFilePending; + nsCString mStreamAsFileName; // When NPP_Destroy is called for our instance (manager), this flag is set // cancels the stream and avoids sending StreamDestroyed. diff --git a/dom/plugins/ipc/BrowserStreamParent.cpp b/dom/plugins/ipc/BrowserStreamParent.cpp index 38ff60b677b0..7c66ee40d281 100644 --- a/dom/plugins/ipc/BrowserStreamParent.cpp +++ b/dom/plugins/ipc/BrowserStreamParent.cpp @@ -2,6 +2,7 @@ #include "BrowserStreamParent.h" #include "PluginInstanceParent.h" +#include "nsNPAPIPlugin.h" #include "mozilla/unused.h" @@ -97,6 +98,8 @@ BrowserStreamParent::RecvStreamDestroyed() return false; } + mStreamPeer = NULL; + mState = DELETING; return Send__delete__(this); } @@ -134,7 +137,15 @@ BrowserStreamParent::StreamAsFile(const char* fname) NS_ASSERTION(ALIVE == mState, "Calling streamasfile after NPP_DestroyStream?"); - unused << CallNPP_StreamAsFile(nsCString(fname)); + // Make sure our stream survives until the plugin process tells us we've + // been destroyed (until RecvStreamDestroyed() is called). Since we retain + // mStreamPeer at most once, we won't get in trouble if StreamAsFile() is + // called more than once. + if (!mStreamPeer) { + nsNPAPIPlugin::RetainStream(mStream, getter_AddRefs(mStreamPeer)); + } + + unused << SendNPP_StreamAsFile(nsCString(fname)); return; } diff --git a/dom/plugins/ipc/BrowserStreamParent.h b/dom/plugins/ipc/BrowserStreamParent.h index e62046e1179b..a39aac747aaa 100644 --- a/dom/plugins/ipc/BrowserStreamParent.h +++ b/dom/plugins/ipc/BrowserStreamParent.h @@ -76,6 +76,7 @@ private: PluginInstanceParent* mNPP; NPStream* mStream; + nsCOMPtr mStreamPeer; enum { ALIVE, diff --git a/dom/plugins/ipc/PBrowserStream.ipdl b/dom/plugins/ipc/PBrowserStream.ipdl index 321f5a7f2a37..4a543ff1a9ab 100644 --- a/dom/plugins/ipc/PBrowserStream.ipdl +++ b/dom/plugins/ipc/PBrowserStream.ipdl @@ -59,7 +59,7 @@ rpc protocol PBrowserStream child: async Write(int32_t offset, Buffer data, uint32_t newlength); - rpc NPP_StreamAsFile(nsCString fname); + async NPP_StreamAsFile(nsCString fname); /** * NPP_DestroyStream may race with other messages: the child acknowledges diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index 5cde0c6d4428..b84e53f1b042 100644 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -116,7 +116,11 @@ PluginModuleParent::LoadModule(const char* aFilePath) TimeoutChanged(kChildTimeoutPref, parent); #ifdef MOZ_CRASHREPORTER - CrashReporterParent::CreateCrashReporter(parent.get()); + // If this fails, we're having IPC troubles, and we're doomed anyways. + if (!CrashReporterParent::CreateCrashReporter(parent.get())) { + parent->mShutdown = true; + return nsnull; + } #endif return parent.forget(); diff --git a/dom/plugins/test/mochitest/test_clear_site_data.html b/dom/plugins/test/mochitest/test_clear_site_data.html index bd5d8dbc9562..564a1db668e1 100644 --- a/dom/plugins/test/mochitest/test_clear_site_data.html +++ b/dom/plugins/test/mochitest/test_clear_site_data.html @@ -2,7 +2,7 @@ NPAPI ClearSiteData/GetSitesWithData Functionality - + diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index dab15390c782..c54c4d655562 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -1355,10 +1355,7 @@ public class GeckoAppShell (int)y); if (GeckoApp.mainLayout.indexOfChild(view) == -1) { - view.setWillNotDraw(false); - if(view instanceof SurfaceView) - ((SurfaceView)view).setZOrderOnTop(true); - + view.setWillNotDraw(true); GeckoApp.mainLayout.addView(view, lp); } else @@ -1412,16 +1409,9 @@ public class GeckoAppShell return null; } - static HashMap sSufaceMap = new HashMap(); - - public static void lockSurfaceANP() + public static SurfaceInfo getSurfaceInfo(SurfaceView sview) { - Log.i("GeckoAppShell", "other lockSurfaceANP"); - } - - public static org.mozilla.gecko.SurfaceLockInfo lockSurfaceANP(android.view.SurfaceView sview, int top, int left, int bottom, int right) - { - Log.i("GeckoAppShell", "real lockSurfaceANP " + sview + ", " + top + ", " + left + ", " + bottom + ", " + right); + Log.i("GeckoAppShell", "getSurfaceInfo " + sview); if (sview == null) return null; @@ -1435,80 +1425,28 @@ public class GeckoAppShell } int n = 0; - if (format == PixelFormat.RGB_565) + if (format == PixelFormat.RGB_565) { n = 2; - else if (format == PixelFormat.RGBA_8888) + } else if (format == PixelFormat.RGBA_8888) { n = 4; - - if (n == 0) + } else { + Log.i("GeckoAppShell", "Unknown pixel format: " + format); return null; - - SurfaceLockInfo info = sSufaceMap.get(sview); - if (info == null) { - info = new SurfaceLockInfo(); - sSufaceMap.put(sview, info); } - Rect r = new Rect(left, top, right, bottom); - - info.canvas = sview.getHolder().lockCanvas(r); - int bufSizeRequired = info.canvas.getWidth() * info.canvas.getHeight() * n; - Log.i("GeckoAppShell", "lockSurfaceANP - bufSizeRequired: " + n + " " + info.canvas.getHeight() + " " + info.canvas.getWidth()); - - if (info.width != info.canvas.getWidth() || info.height != info.canvas.getHeight() || info.buffer == null || info.buffer.capacity() < bufSizeRequired) { - info.width = info.canvas.getWidth(); - info.height = info.canvas.getHeight(); - - // XXX Bitmaps instead of ByteBuffer - info.buffer = ByteBuffer.allocateDirect(bufSizeRequired); //leak - Log.i("GeckoAppShell", "!!!!!!!!!!! lockSurfaceANP - Allocating buffer! " + bufSizeRequired); - - } - - info.canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR); + SurfaceInfo info = new SurfaceInfo(); + Rect r = sview.getHolder().getSurfaceFrame(); + info.width = r.right; + info.height = r.bottom; info.format = format; - info.dirtyTop = top; - info.dirtyBottom = bottom; - info.dirtyLeft = left; - info.dirtyRight = right; return info; } - public static void unlockSurfaceANP(SurfaceView sview) { - SurfaceLockInfo info = sSufaceMap.get(sview); - - int n = 0; - Bitmap.Config config; - if (info.format == PixelFormat.RGB_565) { - n = 2; - config = Bitmap.Config.RGB_565; - } else { - n = 4; - config = Bitmap.Config.ARGB_8888; - } - - Log.i("GeckoAppShell", "unlockSurfaceANP: " + (info.width * info.height * n)); - - Bitmap bm = Bitmap.createBitmap(info.width, info.height, config); - bm.copyPixelsFromBuffer(info.buffer); - info.canvas.drawBitmap(bm, 0, 0, null); - sview.getHolder().unlockCanvasAndPost(info.canvas); - } - - public static Class getSurfaceLockInfoClass() { - Log.i("GeckoAppShell", "class name: " + SurfaceLockInfo.class.getName()); - return SurfaceLockInfo.class; - } - - public static Method getSurfaceLockMethod() { - Method[] m = GeckoAppShell.class.getMethods(); - for (int i = 0; i < m.length; i++) { - if (m[i].getName().equals("lockSurfaceANP")) - return m[i]; - } - return null; + public static Class getSurfaceInfoClass() { + Log.i("GeckoAppShell", "class name: " + SurfaceInfo.class.getName()); + return SurfaceInfo.class; } static native void executeNextRunnable(); diff --git a/embedding/android/Makefile.in b/embedding/android/Makefile.in index 92abf3875d2b..0aec2533e4c9 100644 --- a/embedding/android/Makefile.in +++ b/embedding/android/Makefile.in @@ -53,7 +53,7 @@ JAVAFILES = \ GeckoSurfaceView.java \ GeckoInputConnection.java \ AlertNotification.java \ - SurfaceLockInfo.java \ + SurfaceInfo.java \ $(NULL) PROCESSEDJAVAFILES = \ diff --git a/embedding/android/SurfaceInfo.java b/embedding/android/SurfaceInfo.java new file mode 100644 index 000000000000..f823926a2821 --- /dev/null +++ b/embedding/android/SurfaceInfo.java @@ -0,0 +1,7 @@ +package org.mozilla.gecko; + +public class SurfaceInfo { + public int format; + public int width; + public int height; +} diff --git a/embedding/android/SurfaceLockInfo.java b/embedding/android/SurfaceLockInfo.java deleted file mode 100644 index 4dcb7dc2b6a3..000000000000 --- a/embedding/android/SurfaceLockInfo.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.mozilla.gecko; - -import android.graphics.Canvas; -import java.nio.Buffer; - -public class SurfaceLockInfo { - public int dirtyTop; - public int dirtyLeft; - public int dirtyRight; - public int dirtyBottom; - - public int bpr; - public int format; - public int width; - public int height; - public Buffer buffer; - public Canvas canvas; -} diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla index 346138ee418f..0c9856a20fbe 100644 --- a/gfx/angle/README.mozilla +++ b/gfx/angle/README.mozilla @@ -11,6 +11,7 @@ In this order: angle-limit-identifiers-to-250-chars.patch - see bug 675625 angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands. angle-mCurrentValueOffsets-size_t.patch - ANGLE bug 220 - compile fix on win64 + angle-pool_allocator-assignable.patch - ANGLE r798 In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE. diff --git a/gfx/angle/angle-pool_allocator-assignable.patch b/gfx/angle/angle-pool_allocator-assignable.patch new file mode 100644 index 000000000000..c0cca1d69d1f --- /dev/null +++ b/gfx/angle/angle-pool_allocator-assignable.patch @@ -0,0 +1,55 @@ +diff --git a/gfx/angle/src/compiler/PoolAlloc.h b/gfx/angle/src/compiler/PoolAlloc.h +--- a/gfx/angle/src/compiler/PoolAlloc.h ++++ b/gfx/angle/src/compiler/PoolAlloc.h +@@ -248,22 +248,28 @@ public: + + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + +- pool_allocator() : allocator(GlobalPoolAllocator) { } +- pool_allocator(TPoolAllocator& a) : allocator(a) { } ++ pool_allocator() : allocator(&GlobalPoolAllocator) { } ++ pool_allocator(TPoolAllocator& a) : allocator(&a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + ++ template ++ pool_allocator& operator=(const pool_allocator& p) { ++ allocator = p.allocator; ++ return *this; ++ } ++ + template +- pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } ++ pool_allocator(const pool_allocator& p) : allocator(&p.getAllocator()) { } + + #if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) + // libCStd on some platforms have a different allocate/deallocate interface. + // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be + // allocated, not the number of elements. + void* allocate(size_type n) { + return getAllocator().allocate(n); + } +@@ -285,16 +291,16 @@ public: + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + +- void setAllocator(TPoolAllocator* a) { allocator = *a; } +- TPoolAllocator& getAllocator() const { return allocator; } ++ void setAllocator(TPoolAllocator* a) { allocator = a; } ++ TPoolAllocator& getAllocator() const { return *allocator; } + + protected: +- TPoolAllocator& allocator; ++ TPoolAllocator* allocator; + }; + + #endif // _POOLALLOC_INCLUDED_ diff --git a/gfx/angle/src/compiler/PoolAlloc.h b/gfx/angle/src/compiler/PoolAlloc.h index 55e09dbc4055..a8a59c69acd9 100644 --- a/gfx/angle/src/compiler/PoolAlloc.h +++ b/gfx/angle/src/compiler/PoolAlloc.h @@ -253,12 +253,18 @@ public: pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } - pool_allocator() : allocator(GlobalPoolAllocator) { } - pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator() : allocator(&GlobalPoolAllocator) { } + pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + template + pool_allocator& operator=(const pool_allocator& p) { + allocator = p.allocator; + return *this; + } + template - pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + pool_allocator(const pool_allocator& p) : allocator(&p.getAllocator()) { } #if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR) // libCStd on some platforms have a different allocate/deallocate interface. @@ -290,11 +296,11 @@ public: size_type max_size() const { return static_cast(-1) / sizeof(T); } size_type max_size(int size) const { return static_cast(-1) / size; } - void setAllocator(TPoolAllocator* a) { allocator = *a; } - TPoolAllocator& getAllocator() const { return allocator; } + void setAllocator(TPoolAllocator* a) { allocator = a; } + TPoolAllocator& getAllocator() const { return *allocator; } protected: - TPoolAllocator& allocator; + TPoolAllocator* allocator; }; #endif // _POOLALLOC_INCLUDED_ diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 647686612b2c..9e9b852cb2c6 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -1111,7 +1111,7 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface) mGLContext->MakeCurrent(); #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE) - mGLContext->fFinish(); + mGLContext->Finish(); gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface(); // XRender can only blend premuliplied alpha, so only allow xrender diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp index c298c0846897..c1338e0945fc 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -172,6 +172,10 @@ CanvasLayerOGL::UpdateSurface() } #endif + if (mCanvasGLContext) { + mCanvasGLContext->MakeCurrent(); + mCanvasGLContext->fFinish(); + } mOGLManager->MakeCurrent(); if (mCanvasGLContext && diff --git a/gfx/thebes/GLContext.cpp b/gfx/thebes/GLContext.cpp index fa6e67090ca6..29220ef55f29 100644 --- a/gfx/thebes/GLContext.cpp +++ b/gfx/thebes/GLContext.cpp @@ -377,6 +377,33 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer), "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!"); + // Check for aux symbols based on extensions + if (IsExtensionSupported(GLContext::ANGLE_framebuffer_blit) || + IsExtensionSupported(GLContext::EXT_framebuffer_blit)) { + SymLoadStruct auxSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBlitFramebuffer, { "BlitFramebuffer", "BlitFramebufferEXT", "BlitFramebufferANGLE", NULL } }, + { NULL, { NULL } }, + }; + if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) { + NS_RUNTIMEABORT("GL supports framebuffer_blit without supplying glBlitFramebuffer"); + mInitialized = false; + } + } + + if (IsExtensionSupported(GLContext::ANGLE_framebuffer_multisample) || + IsExtensionSupported(GLContext::EXT_framebuffer_multisample)) { + SymLoadStruct auxSymbols[] = { + { (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample, { "RenderbufferStorageMultisample", "RenderbufferStorageMultisampleEXT", "RenderbufferStorageMultisampleANGLE", NULL } }, + { NULL, { NULL } }, + }; + if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) { + NS_RUNTIMEABORT("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample"); + mInitialized = false; + } + } + } + + if (mInitialized) { GLint v[4]; fGetIntegerv(LOCAL_GL_SCISSOR_BOX, v); @@ -438,6 +465,11 @@ static const char *sExtensionNames[] = { "GL_ARB_texture_float", "GL_EXT_unpack_subimage", "GL_OES_standard_derivatives", + "GL_EXT_framebuffer_blit", + "GL_ANGLE_framebuffer_blit", + "GL_EXT_framebuffer_multisample", + "GL_ANGLE_framebuffer_multisample", + "GL_OES_rgb8_rgba8", NULL }; @@ -986,107 +1018,155 @@ PRUint32 TiledTextureImage::GetTileCount() } bool -GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize) +GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA) { if (!IsOffscreenSizeAllowed(aSize)) return false; MakeCurrent(); - bool alpha = mCreationFormat.alpha > 0; - int depth = mCreationFormat.depth; - int stencil = mCreationFormat.stencil; + const bool alpha = mCreationFormat.alpha > 0; + const int depth = mCreationFormat.depth; + const int stencil = mCreationFormat.stencil; + int samples = mCreationFormat.samples; - bool firstTime = (mOffscreenFBO == 0); + const bool useDrawMSFBO = (samples > 0) && SupportsFramebufferMultisample(); - GLuint curBoundTexture = 0; + if (!useDrawMSFBO && !aUseReadFBO) + return true; + + if (!useDrawMSFBO || aDisableAA) + samples = 0; + + const bool firstTime = (mOffscreenDrawFBO == 0 && mOffscreenReadFBO == 0); + + GLuint curBoundFramebufferDraw = 0; + GLuint curBoundFramebufferRead = 0; GLuint curBoundRenderbuffer = 0; - GLuint curBoundFramebuffer = 0; + GLuint curBoundTexture = 0; GLint viewport[4]; - bool useDepthStencil = - !mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil); + const bool useDepthStencil = + !mIsGLES2 || IsExtensionSupported(OES_packed_depth_stencil); // save a few things for later restoring - fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture); - fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*) &curBoundFramebuffer); + curBoundFramebufferDraw = GetBoundDrawFBO(); + curBoundFramebufferRead = GetBoundReadFBO(); fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, (GLint*) &curBoundRenderbuffer); + fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &curBoundTexture); fGetIntegerv(LOCAL_GL_VIEWPORT, viewport); - // the context format of what we're defining; - // for some reason, UpdateActualFormat isn't working with a bound FBO. - ContextFormat cf; + // the context format of what we're defining + // This becomes mActualFormat on success + ContextFormat cf(mCreationFormat); - // If this is the first time we're going through this, we need - // to create the objects we'll use. Otherwise, just bind them. - if (firstTime) { - fGenTextures(1, &mOffscreenTexture); - fBindTexture(LOCAL_GL_TEXTURE_2D, mOffscreenTexture); - fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); - fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); + // Create everything we need for the resize, so if it fails, we haven't broken anything + // If successful, these new resized objects will replace their associated member vars in GLContext + GLuint newOffscreenDrawFBO = 0; + GLuint newOffscreenReadFBO = 0; + GLuint newOffscreenTexture = 0; + GLuint newOffscreenColorRB = 0; + GLuint newOffscreenDepthRB = 0; + GLuint newOffscreenStencilRB = 0; - fGenFramebuffers(1, &mOffscreenFBO); - fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO); - - if (depth && stencil && useDepthStencil) { - fGenRenderbuffers(1, &mOffscreenDepthRB); - } else { - if (depth) { - fGenRenderbuffers(1, &mOffscreenDepthRB); - } - - if (stencil) { - fGenRenderbuffers(1, &mOffscreenStencilRB); - } - } - } else { - fBindTexture(LOCAL_GL_TEXTURE_2D, mOffscreenTexture); - fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mOffscreenFBO); + // Create the buffers and texture + if (aUseReadFBO) { + fGenFramebuffers(1, &newOffscreenReadFBO); + fGenTextures(1, &newOffscreenTexture); } - // resize the FBO components - if (alpha) { - fTexImage2D(LOCAL_GL_TEXTURE_2D, - 0, - LOCAL_GL_RGBA, - aSize.width, aSize.height, - 0, - LOCAL_GL_RGBA, - LOCAL_GL_UNSIGNED_BYTE, - NULL); - - cf.red = cf.green = cf.blue = cf.alpha = 8; + if (useDrawMSFBO) { + fGenFramebuffers(1, &newOffscreenDrawFBO); + fGenRenderbuffers(1, &newOffscreenColorRB); } else { - fTexImage2D(LOCAL_GL_TEXTURE_2D, - 0, - LOCAL_GL_RGB, - aSize.width, aSize.height, - 0, - LOCAL_GL_RGB, -#ifdef XP_WIN - LOCAL_GL_UNSIGNED_BYTE, -#else - mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5 - : LOCAL_GL_UNSIGNED_BYTE, -#endif - NULL); - -#ifdef XP_WIN - cf.red = cf.green = cf.blue = 8; -#else - cf.red = 5; - cf.green = 6; - cf.blue = 5; -#endif - cf.alpha = 0; + newOffscreenDrawFBO = newOffscreenReadFBO; } if (depth && stencil && useDepthStencil) { - fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB); - fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, - LOCAL_GL_DEPTH24_STENCIL8, - aSize.width, aSize.height); + fGenRenderbuffers(1, &newOffscreenDepthRB); + } else { + if (depth) { + fGenRenderbuffers(1, &newOffscreenDepthRB); + } + + if (stencil) { + fGenRenderbuffers(1, &newOffscreenStencilRB); + } + } + + // Allocate texture + if (aUseReadFBO) { + fBindTexture(LOCAL_GL_TEXTURE_2D, newOffscreenTexture); + fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); + fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); + + if (alpha) { + fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + LOCAL_GL_RGBA, + aSize.width, aSize.height, + 0, + LOCAL_GL_RGBA, + LOCAL_GL_UNSIGNED_BYTE, + NULL); + + cf.red = cf.green = cf.blue = cf.alpha = 8; + } else { + fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + LOCAL_GL_RGB, + aSize.width, aSize.height, + 0, + LOCAL_GL_RGB, +#ifdef XP_WIN + LOCAL_GL_UNSIGNED_BYTE, +#else + mIsGLES2 ? LOCAL_GL_UNSIGNED_SHORT_5_6_5 + : LOCAL_GL_UNSIGNED_BYTE, +#endif + NULL); + +#ifdef XP_WIN + cf.red = cf.green = cf.blue = 8; +#else + cf.red = 5; + cf.green = 6; + cf.blue = 5; +#endif + cf.alpha = 0; + } + } + cf.samples = samples; + + // Allocate color buffer + if (useDrawMSFBO) { + GLenum colorFormat; + if (!mIsGLES2 || IsExtensionSupported(OES_rgb8_rgba8)) + colorFormat = alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8; + else + colorFormat = alpha ? LOCAL_GL_RGBA4 : LOCAL_GL_RGB565; + + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenColorRB); + fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, + samples, + colorFormat, + aSize.width, aSize.height); + } + + // Allocate depth and stencil buffers + if (depth && stencil && useDepthStencil) { + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB); + if (useDrawMSFBO) { + fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, + samples, + LOCAL_GL_DEPTH24_STENCIL8, + aSize.width, aSize.height); + } else { + fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, + LOCAL_GL_DEPTH24_STENCIL8, + aSize.width, aSize.height); + } cf.depth = 24; cf.stencil = 8; } else { @@ -1108,77 +1188,167 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize) cf.depth = 24; } - fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenDepthRB); - fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, depthType, - aSize.width, aSize.height); + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenDepthRB); + if (useDrawMSFBO) { + fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, + samples, + depthType, + aSize.width, aSize.height); + } else { + fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, + depthType, + aSize.width, aSize.height); + } } if (stencil) { - fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOffscreenStencilRB); - fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, - LOCAL_GL_STENCIL_INDEX8, - aSize.width, aSize.height); + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, newOffscreenStencilRB); + if (useDrawMSFBO) { + fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, + samples, + LOCAL_GL_STENCIL_INDEX8, + aSize.width, aSize.height); + } else { + fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, + LOCAL_GL_STENCIL_INDEX8, + aSize.width, aSize.height); + } cf.stencil = 8; } } - // Now assemble the FBO, if we're creating one - // for the first time. - if (firstTime) { - fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_COLOR_ATTACHMENT0, - LOCAL_GL_TEXTURE_2D, - mOffscreenTexture, - 0); + // Now assemble the FBO + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO); // If we're not using a separate draw FBO, this will be the read FBO + if (useDrawMSFBO) { + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_RENDERBUFFER, + newOffscreenColorRB); + } - if (depth && stencil && useDepthStencil) { + if (depth && stencil && useDepthStencil) { + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_DEPTH_ATTACHMENT, + LOCAL_GL_RENDERBUFFER, + newOffscreenDepthRB); + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_STENCIL_ATTACHMENT, + LOCAL_GL_RENDERBUFFER, + newOffscreenDepthRB); + } else { + if (depth) { fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, - mOffscreenDepthRB); + newOffscreenDepthRB); + } + + if (stencil) { fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, - mOffscreenDepthRB); - } else { - if (depth) { - fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_DEPTH_ATTACHMENT, - LOCAL_GL_RENDERBUFFER, - mOffscreenDepthRB); - } - - if (stencil) { - fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, - LOCAL_GL_STENCIL_ATTACHMENT, - LOCAL_GL_RENDERBUFFER, - mOffscreenStencilRB); - } + newOffscreenStencilRB); } } + if (aUseReadFBO) { + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO); + fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, + newOffscreenTexture, + 0); + } + // We should be all resized. Check for framebuffer completeness. - GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + GLenum status; + bool framebuffersComplete = true; + + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenDrawFBO); + status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) { - NS_WARNING("Error resizing offscreen framebuffer -- framebuffer not complete"); + NS_WARNING("DrawFBO: Incomplete"); +#ifdef DEBUG + printf_stderr("Framebuffer status: %X\n", status); +#endif + framebuffersComplete = false; + } + + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, newOffscreenReadFBO); + status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) { + NS_WARNING("ReadFBO: Incomplete"); +#ifdef DEBUG + printf_stderr("Framebuffer status: %X\n", status); +#endif + framebuffersComplete = false; + } + + if (!framebuffersComplete) { + NS_WARNING("Error resizing offscreen framebuffer -- framebuffer(s) not complete"); + + // Clean up the mess + fDeleteFramebuffers(1, &newOffscreenDrawFBO); + fDeleteFramebuffers(1, &newOffscreenReadFBO); + fDeleteTextures(1, &newOffscreenTexture); + fDeleteRenderbuffers(1, &newOffscreenColorRB); + fDeleteRenderbuffers(1, &newOffscreenDepthRB); + fDeleteRenderbuffers(1, &newOffscreenStencilRB); + + BindReadFBO(curBoundFramebufferRead); + BindDrawFBO(curBoundFramebufferDraw); + fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture); + fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer); + fViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + return false; } + // Success, so delete the old and busted + fDeleteFramebuffers(1, &mOffscreenDrawFBO); + fDeleteFramebuffers(1, &mOffscreenReadFBO); + fDeleteTextures(1, &mOffscreenTexture); + fDeleteRenderbuffers(1, &mOffscreenColorRB); + fDeleteRenderbuffers(1, &mOffscreenDepthRB); + fDeleteRenderbuffers(1, &mOffscreenStencilRB); + + // Update currently bound references if we're changing what they were point to + // This way we don't rebind to old buffers when we're done here + if (curBoundFramebufferDraw == mOffscreenDrawFBO) + curBoundFramebufferDraw = newOffscreenDrawFBO; + if (curBoundFramebufferRead == mOffscreenReadFBO) + curBoundFramebufferRead = newOffscreenReadFBO; + if (curBoundTexture == mOffscreenTexture) + curBoundTexture = newOffscreenTexture; + if (curBoundRenderbuffer == mOffscreenColorRB) + curBoundRenderbuffer = newOffscreenColorRB; + else if (curBoundRenderbuffer == mOffscreenDepthRB) + curBoundRenderbuffer = newOffscreenDepthRB; + else if (curBoundRenderbuffer == mOffscreenStencilRB) + curBoundRenderbuffer = newOffscreenStencilRB; + + // Replace with the new hotness + mOffscreenDrawFBO = newOffscreenDrawFBO; + mOffscreenReadFBO = newOffscreenReadFBO; + mOffscreenTexture = newOffscreenTexture; + mOffscreenColorRB = newOffscreenColorRB; + mOffscreenDepthRB = newOffscreenDepthRB; + mOffscreenStencilRB = newOffscreenStencilRB; + mOffscreenSize = aSize; mOffscreenActualSize = aSize; - if (firstTime) { - // UpdateActualFormat() doesn't work for some reason, with a - // FBO bound, even though it should. - //UpdateActualFormat(); - mActualFormat = cf; + mActualFormat = cf; #ifdef DEBUG - printf_stderr("Created offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d\n", + if (mDebugMode) { + printf_stderr("%s %dx%d offscreen FBO: r: %d g: %d b: %d a: %d depth: %d stencil: %d samples: %d\n", + firstTime ? "Created" : "Resized", + mOffscreenActualSize.width, mOffscreenActualSize.height, mActualFormat.red, mActualFormat.green, mActualFormat.blue, mActualFormat.alpha, - mActualFormat.depth, mActualFormat.stencil); -#endif + mActualFormat.depth, mActualFormat.stencil, mActualFormat.samples); } +#endif // We're good, and the framebuffer is already attached, so let's // clear out our new framebuffer; otherwise we'll end up displaying @@ -1186,13 +1356,18 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize) // can restore them. fViewport(0, 0, aSize.width, aSize.height); + // Make sure we know that the buffers are new and thus dirty: + ForceDirtyFBOs(); + // Clear the new framebuffer with the full viewport + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, GetOffscreenFBO()); ClearSafely(); // Ok, now restore the GL state back to what it was before the resize took place. + BindDrawFBO(curBoundFramebufferDraw); + BindReadFBO(curBoundFramebufferRead); fBindTexture(LOCAL_GL_TEXTURE_2D, curBoundTexture); fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, curBoundRenderbuffer); - fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, curBoundFramebuffer); // -don't- restore the viewport the first time through this, since // the previous one isn't valid. @@ -1205,13 +1380,17 @@ GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize) void GLContext::DeleteOffscreenFBO() { - fDeleteFramebuffers(1, &mOffscreenFBO); + fDeleteFramebuffers(1, &mOffscreenDrawFBO); + fDeleteFramebuffers(1, &mOffscreenReadFBO); fDeleteTextures(1, &mOffscreenTexture); + fDeleteRenderbuffers(1, &mOffscreenColorRB); fDeleteRenderbuffers(1, &mOffscreenDepthRB); fDeleteRenderbuffers(1, &mOffscreenStencilRB); - mOffscreenFBO = 0; + mOffscreenDrawFBO = 0; + mOffscreenReadFBO = 0; mOffscreenTexture = 0; + mOffscreenColorRB = 0; mOffscreenDepthRB = 0; mOffscreenStencilRB = 0; } diff --git a/gfx/thebes/GLContext.h b/gfx/thebes/GLContext.h index 0f9032f3fa2c..0e20eb2ce235 100644 --- a/gfx/thebes/GLContext.h +++ b/gfx/thebes/GLContext.h @@ -476,11 +476,11 @@ struct THEBES_API ContextFormat }; ContextFormat() { - memset(this, 0, sizeof(*this)); + memset(this, 0, sizeof(ContextFormat)); } ContextFormat(const StandardContextFormat cf) { - memset(this, 0, sizeof(*this)); + memset(this, 0, sizeof(ContextFormat)); switch (cf) { case BasicRGBA32: red = green = blue = alpha = 8; @@ -519,6 +519,7 @@ struct THEBES_API ContextFormat int green, minGreen; int blue, minBlue; int alpha, minAlpha; + int samples; int colorBits() const { return red + green + blue; } }; @@ -547,7 +548,10 @@ public: mFlipped(false), mBlitProgram(0), mBlitFramebuffer(0), - mOffscreenFBO(0), + mOffscreenDrawFBO(0), + mOffscreenReadFBO(0), + mOffscreenFBOsDirty(false), + mOffscreenColorRB(0), mOffscreenDepthRB(0), mOffscreenStencilRB(0) #ifdef DEBUG @@ -719,7 +723,7 @@ public: return false; } - if (!aOffscreen->mOffscreenFBO) { + if (!aOffscreen->mOffscreenDrawFBO && !aOffscreen->mOffscreenReadFBO) { return false; } @@ -749,8 +753,8 @@ public: * Only valid if IsOffscreen() returns true. */ virtual bool ResizeOffscreen(const gfxIntSize& aNewSize) { - if (mOffscreenFBO) - return ResizeOffscreenFBO(aNewSize); + if (mOffscreenDrawFBO || mOffscreenReadFBO) + return ResizeOffscreenFBO(aNewSize, mOffscreenReadFBO != 0); return false; } @@ -781,12 +785,232 @@ public: * Only valid if IsOffscreen() returns true. */ GLuint GetOffscreenFBO() { - return mOffscreenFBO; + // 0 is interpreted as (off)screen, whether for read or draw operations + return 0; } + GLuint GetOffscreenTexture() { return mOffscreenTexture; } + virtual bool SupportsFramebufferMultisample() { + return IsExtensionSupported(EXT_framebuffer_multisample) || IsExtensionSupported(ANGLE_framebuffer_multisample); + } + + virtual bool SupportsOffscreenSplit() { + return IsExtensionSupported(EXT_framebuffer_blit) || IsExtensionSupported(ANGLE_framebuffer_blit); + } + + GLuint GetBoundDrawFBO() { + GLint ret = 0; + if (SupportsOffscreenSplit()) + fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret); + else + fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret); + return ret; + } + + GLuint GetBoundReadFBO() { + GLint ret = 0; + if (SupportsOffscreenSplit()) + fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, &ret); + else + fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret); + return ret; + } + + void BindDrawFBO(GLuint name) { + if (SupportsOffscreenSplit()) + fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, name); + else + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name); + } + + void BindReadFBO(GLuint name) { + if (SupportsOffscreenSplit()) + fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, name); + else + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, name); + } + + GLuint SwapBoundDrawFBO(GLuint name) { + GLuint prev = GetBoundDrawFBO(); + BindDrawFBO(name); + return prev; + } + + GLuint SwapBoundReadFBO(GLuint name) { + GLuint prev = GetBoundReadFBO(); + BindReadFBO(name); + return prev; + } + + void BindOffscreenDrawBuffer() { + BindDrawFBO(mOffscreenDrawFBO); + } + + void BindOffscreenReadBuffer() { + BindReadFBO(mOffscreenReadFBO); + } + + void BindOffscreenBuffers() { + BindOffscreenDrawBuffer(); + BindOffscreenReadBuffer(); + } + +private: + GLuint mPrevDrawFBOBinding; + GLuint mPrevReadFBOBinding; + bool mOffscreenFBOsDirty; + + void BeforeGLDrawCall() { + // Record and rebind if necessary + mPrevDrawFBOBinding = GetBoundDrawFBO(); + if (mPrevDrawFBOBinding == 0) { + BindDrawFBO(mOffscreenDrawFBO); + } else if (mPrevDrawFBOBinding != mOffscreenDrawFBO) + return; + + // Must be after binding the proper FBO + if (mOffscreenDrawFBO == mOffscreenReadFBO) + return; + + // If we're already dirty, no need to set it again + if (mOffscreenFBOsDirty) + return; + + mOffscreenFBOsDirty = true; + } + + void AfterGLDrawCall() { + if (mPrevDrawFBOBinding == 0) { + BindDrawFBO(0); + } + } + + void BeforeGLReadCall() { + // Record and rebind if necessary + mPrevReadFBOBinding = GetBoundReadFBO(); + if (mPrevReadFBOBinding == 0) { + BindReadFBO(mOffscreenReadFBO); + } else if (mPrevReadFBOBinding != mOffscreenReadFBO) + return; + + // Must be after binding the proper FBO + if (mOffscreenDrawFBO == mOffscreenReadFBO) + return; + + // If we're not dirty, there's no need to blit + if (!mOffscreenFBOsDirty) + return; + + const bool scissor = fIsEnabled(LOCAL_GL_SCISSOR_TEST); + if (scissor) + fDisable(LOCAL_GL_SCISSOR_TEST); + + // flip read/draw for blitting + GLuint prevDraw = SwapBoundDrawFBO(mOffscreenReadFBO); + BindReadFBO(mOffscreenDrawFBO); // We know that Read must already be mOffscreenRead, so no need to write that down + + GLint width = mOffscreenActualSize.width; + GLint height = mOffscreenActualSize.height; + raw_fBlitFramebuffer(0, 0, width, height, + 0, 0, width, height, + LOCAL_GL_COLOR_BUFFER_BIT, + LOCAL_GL_NEAREST); + + BindDrawFBO(prevDraw); + BindReadFBO(mOffscreenReadFBO); + + if (scissor) + fEnable(LOCAL_GL_SCISSOR_TEST); + + mOffscreenFBOsDirty = false; + } + + void AfterGLReadCall() { + if (mPrevReadFBOBinding == 0) { + BindReadFBO(0); + } + } + +public: + // Draw call hooks: + void fClear(GLbitfield mask) { + BeforeGLDrawCall(); + raw_fClear(mask); + AfterGLDrawCall(); + } + + void fDrawArrays(GLenum mode, GLint first, GLsizei count) { + BeforeGLDrawCall(); + raw_fDrawArrays(mode, first, count); + AfterGLDrawCall(); + } + + void fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { + BeforeGLDrawCall(); + raw_fDrawElements(mode, count, type, indices); + AfterGLDrawCall(); + } + + // Read call hooks: + void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { + BeforeGLReadCall(); + raw_fReadPixels(x, y, width, height, format, type, pixels); + AfterGLReadCall(); + } + + void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + BeforeGLReadCall(); + raw_fCopyTexImage2D(target, level, internalformat, + x, y, width, height, border); + AfterGLReadCall(); + } + + void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + BeforeGLReadCall(); + raw_fCopyTexSubImage2D(target, level, xoffset, yoffset, + x, y, width, height); + AfterGLReadCall(); + } + + void ForceDirtyFBOs() { + GLuint draw = SwapBoundReadFBO(mOffscreenDrawFBO); + + BeforeGLDrawCall(); + // no-op; just pretend we did something + AfterGLDrawCall(); + + BindDrawFBO(draw); + } + + void BlitDirtyFBOs() { + GLuint read = SwapBoundReadFBO(mOffscreenReadFBO); + + BeforeGLReadCall(); + // no-op; we just want to make sure the Read FBO is updated if it needs to be + AfterGLReadCall(); + + BindReadFBO(read); + } + + // Before reads from offscreen texture + void fFinish() { + BeforeGLReadCall(); + raw_fFinish(); + AfterGLReadCall(); + } + + // Draw/Read + void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + BeforeGLDrawCall(); + BeforeGLReadCall(); + raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + AfterGLReadCall(); + AfterGLDrawCall(); + } + #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) virtual gfxASurface* GetOffscreenPixmapSurface() { @@ -1013,6 +1237,11 @@ public: ARB_texture_float, EXT_unpack_subimage, OES_standard_derivatives, + EXT_framebuffer_blit, + ANGLE_framebuffer_blit, + EXT_framebuffer_multisample, + ANGLE_framebuffer_multisample, + OES_rgb8_rgba8, Extensions_Max }; @@ -1092,9 +1321,20 @@ protected: // helper to create/resize an offscreen FBO, // for offscreen implementations that use FBOs. - bool ResizeOffscreenFBO(const gfxIntSize& aSize); + bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO, const bool aDisableAA); + bool ResizeOffscreenFBO(const gfxIntSize& aSize, const bool aUseReadFBO) { + if (ResizeOffscreenFBO(aSize, aUseReadFBO, false)) + return true; + + if (!mCreationFormat.samples) + return false; + printf("ResizeOffscreenFBO failed with AA, retrying without...\n"); + return ResizeOffscreenFBO(aSize, aUseReadFBO, true); + } void DeleteOffscreenFBO(); - GLuint mOffscreenFBO; + GLuint mOffscreenDrawFBO; + GLuint mOffscreenReadFBO; + GLuint mOffscreenColorRB; GLuint mOffscreenDepthRB; GLuint mOffscreenStencilRB; @@ -1454,7 +1694,7 @@ public: AFTER_GL_CALL; } - void fClear(GLbitfield mask) { + void raw_fClear(GLbitfield mask) { BEFORE_GL_CALL; mSymbols.fClear(mask); AFTER_GL_CALL; @@ -1514,13 +1754,13 @@ public: AFTER_GL_CALL; } - void fDrawArrays(GLenum mode, GLint first, GLsizei count) { + void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) { BEFORE_GL_CALL; mSymbols.fDrawArrays(mode, first, count); AFTER_GL_CALL; } - void fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { + void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { BEFORE_GL_CALL; mSymbols.fDrawElements(mode, count, type, indices); AFTER_GL_CALL; @@ -1538,7 +1778,7 @@ public: AFTER_GL_CALL; } - void fFinish() { + void raw_fFinish() { BEFORE_GL_CALL; mSymbols.fFinish(); AFTER_GL_CALL; @@ -1756,7 +1996,7 @@ public: AFTER_GL_CALL; } - void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { + void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) { BEFORE_GL_CALL; mSymbols.fReadPixels(x, y, width, height, format, type, pixels); AFTER_GL_CALL; @@ -2002,7 +2242,7 @@ public: AFTER_GL_CALL; } - void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { BEFORE_GL_CALL; mSymbols.fCopyTexImage2D(target, level, internalformat, x, FixYValue(y, height), @@ -2010,7 +2250,7 @@ public: AFTER_GL_CALL; } - void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { BEFORE_GL_CALL; mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset, x, FixYValue(y, height), @@ -2092,6 +2332,12 @@ public: return retval; } + void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + BEFORE_GL_CALL; + mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + AFTER_GL_CALL; + } + realGLboolean fIsRenderbuffer (GLuint renderbuffer) { BEFORE_GL_CALL; realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer); @@ -2105,6 +2351,12 @@ public: AFTER_GL_CALL; } + void fRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) { + BEFORE_GL_CALL; + mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat, width, height); + AFTER_GL_CALL; + } + void fDepthRange(GLclampf a, GLclampf b) { BEFORE_GL_CALL; if (mIsGLES2) { diff --git a/gfx/thebes/GLContextProviderCGL.mm b/gfx/thebes/GLContextProviderCGL.mm index cda582aa955d..908a977fdc9c 100644 --- a/gfx/thebes/GLContextProviderCGL.mm +++ b/gfx/thebes/GLContextProviderCGL.mm @@ -46,6 +46,7 @@ #include "gfxPlatform.h" #include "gfxFailure.h" #include "prenv.h" +#include "mozilla/Preferences.h" namespace mozilla { namespace gl { @@ -263,6 +264,9 @@ GLContextCGL::UnbindTex2DOffscreen(GLContext *aOffscreen) bool GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize) { + if (!IsOffscreenSizeAllowed(aNewSize)) + return false; + if (mPBuffer) { NSOpenGLPixelBuffer *pb = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:LOCAL_GL_TEXTURE_2D @@ -274,6 +278,10 @@ GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize) return false; } + if (!ResizeOffscreenFBO(aNewSize, false)) { + return false; + } + [mPBuffer release]; mPBuffer = pb; @@ -289,7 +297,7 @@ GLContextCGL::ResizeOffscreen(const gfxIntSize& aNewSize) return true; } - return ResizeOffscreenFBO(aNewSize); + return ResizeOffscreenFBO(aNewSize, true); } class TextureImageCGL : public BasicTextureImage @@ -528,8 +536,7 @@ CreateOffscreenPBufferContext(const gfxIntSize& aSize, } static already_AddRefed -CreateOffscreenFBOContext(const gfxIntSize& aSize, - const ContextFormat& aFormat, +CreateOffscreenFBOContext(const ContextFormat& aFormat, bool aShare = true) { if (!sCGLLibrary.EnsureInitialized()) { @@ -557,23 +564,34 @@ already_AddRefed GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize, const ContextFormat& aFormat) { + ContextFormat actualFormat(aFormat); + actualFormat.samples = 0; + nsRefPtr glContext; - - glContext = CreateOffscreenPBufferContext(aSize, aFormat); - if (glContext && - glContext->Init()) + + NS_ENSURE_TRUE(Preferences::GetRootBranch(), nsnull); + const bool preferFBOs = Preferences::GetBool("cgl.prefer-fbo", false); + if (!preferFBOs) { - glContext->mOffscreenSize = aSize; - glContext->mOffscreenActualSize = aSize; + glContext = CreateOffscreenPBufferContext(aSize, actualFormat); + if (glContext && + glContext->Init() && + glContext->ResizeOffscreenFBO(aSize, false)) + { + glContext->mOffscreenSize = aSize; + glContext->mOffscreenActualSize = aSize; - return glContext.forget(); + printf("GL Offscreen: CGL+PBuffer\n"); + + return glContext.forget(); + } } // try a FBO as second choice - glContext = CreateOffscreenFBOContext(aSize, aFormat); + glContext = CreateOffscreenFBOContext(actualFormat); if (glContext && glContext->Init() && - glContext->ResizeOffscreenFBO(aSize)) + glContext->ResizeOffscreenFBO(aSize, true)) { return glContext.forget(); } @@ -602,8 +620,7 @@ GLContextProviderCGL::GetGlobalContext() // than 16x16 in size; also 16x16 is POT so that we can do // a FBO with it on older video cards. A FBO context for // sharing is preferred since it has no associated target. - gGlobalContext = CreateOffscreenFBOContext(gfxIntSize(16, 16), - ContextFormat(ContextFormat::BasicRGB24), + gGlobalContext = CreateOffscreenFBOContext(ContextFormat(ContextFormat::BasicRGB24), false); if (!gGlobalContext || !static_cast(gGlobalContext.get())->Init()) { NS_WARNING("Couldn't init gGlobalContext."); diff --git a/gfx/thebes/GLContextProviderEGL.cpp b/gfx/thebes/GLContextProviderEGL.cpp index 7d9a095db7be..7f5d4ac60866 100644 --- a/gfx/thebes/GLContextProviderEGL.cpp +++ b/gfx/thebes/GLContextProviderEGL.cpp @@ -1054,6 +1054,9 @@ GLContextEGL::UnbindTex2DOffscreen(GLContext *aOffscreen) bool GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize) { + if (!IsOffscreenSizeAllowed(aNewSize)) + return false; + if (mIsPBuffer) { gfxIntSize pbsize(aNewSize); @@ -1067,9 +1070,12 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize) pbsize); if (!surface) { NS_WARNING("Failed to resize pbuffer"); - return nsnull; + return false; } + if (!ResizeOffscreenFBO(pbsize, false)) + return false; + SetOffscreenSize(aNewSize, pbsize); if (mSurface && !mPlatformContext) { @@ -1114,6 +1120,9 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize) if (!config) { return false; } + if (!ResizeOffscreenFBO(aNewSize, true)) + return false; + mThebesSurface = xsurface; return true; @@ -1121,10 +1130,13 @@ GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize) #endif #if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) - return ResizeOffscreenPixmapSurface(aNewSize); + if (ResizeOffscreenPixmapSurface(aNewSize)) { + if (ResizeOffscreenFBO(aNewSize, true)) + return true; + } #endif - return ResizeOffscreenFBO(aNewSize); + return ResizeOffscreenFBO(aNewSize, true); } @@ -1999,13 +2011,15 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(const gfxIntSize& aSize, nsTArray attribs(32); int attribAttempt = 0; + int tryDepthSize = (aFormat.depth > 0) ? 24 : 0; + TRY_ATTRIBS_AGAIN: switch (attribAttempt) { case 0: - FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, 8, 24); + FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, 8, tryDepthSize); break; case 1: - FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, 24); + FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, tryDepthSize); break; case 2: FillPBufferAttribs(attribs, aFormat, configCanBindToTexture, -1, -1); @@ -2237,14 +2251,38 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize, if (!sEGLLibrary.EnsureInitialized()) { return nsnull; } + + ContextFormat actualFormat(aFormat); + // actualFormat.samples = 0; #if defined(ANDROID) || defined(XP_WIN) - return GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, aFormat); + nsRefPtr glContext = + GLContextEGL::CreateEGLPBufferOffscreenContext(aSize, actualFormat); + + if (!glContext) + return nsnull; + + if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), false)) + return nsnull; + + printf("GL Offscreen: EGL+PBuffer\n"); + return glContext.forget(); + #elif defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE) - return GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, aFormat); + nsRefPtr glContext = + GLContextEGL::CreateBasicEGLPixmapOffscreenContext(aSize, actualFormat); + + if (!glContext) + return nsnull; + + if (!glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true)) + return nsnull; + + printf("GL Offscreen: EGL+Pixmap\n"); + return glContext.forget(); #elif defined(MOZ_X11) nsRefPtr glContext = - GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, aFormat, true); + GLContextEGL::CreateEGLPixmapOffscreenContext(aSize, actualFormat, true); if (!glContext) { return nsnull; @@ -2254,7 +2292,7 @@ GLContextProviderEGL::CreateOffscreen(const gfxIntSize& aSize, // render from this return nsnull; } - if (!gUseBackingSurface && !glContext->ResizeOffscreenFBO(aSize)) { + if (!gUseBackingSurface && !glContext->ResizeOffscreenFBO(glContext->OffscreenActualSize(), true)) { // we weren't able to create the initial // offscreen FBO, so this is dead return nsnull; diff --git a/gfx/thebes/GLContextProviderGLX.cpp b/gfx/thebes/GLContextProviderGLX.cpp index 41b575702dc5..cede02b5644b 100644 --- a/gfx/thebes/GLContextProviderGLX.cpp +++ b/gfx/thebes/GLContextProviderGLX.cpp @@ -1237,9 +1237,11 @@ already_AddRefed GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize, const ContextFormat& aFormat) { + ContextFormat actualFormat(aFormat); + // actualFormat.samples = 0; nsRefPtr glContext = - CreateOffscreenPixmapContext(aSize, aFormat, true); + CreateOffscreenPixmapContext(aSize, actualFormat, true); if (!glContext) { return nsnull; @@ -1251,7 +1253,7 @@ GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize, return nsnull; } - if (!glContext->ResizeOffscreenFBO(aSize)) { + if (!glContext->ResizeOffscreenFBO(aSize, true)) { // we weren't able to create the initial // offscreen FBO, so this is dead return nsnull; diff --git a/gfx/thebes/GLContextProviderOSMesa.cpp b/gfx/thebes/GLContextProviderOSMesa.cpp index da07beac91bd..4290c8ba7367 100644 --- a/gfx/thebes/GLContextProviderOSMesa.cpp +++ b/gfx/thebes/GLContextProviderOSMesa.cpp @@ -259,7 +259,10 @@ GLContextProviderOSMesa::CreateOffscreen(const gfxIntSize& aSize, return nsnull; } - nsRefPtr glContext = new GLContextOSMesa(aFormat); + ContextFormat actualFormat(aFormat); + actualFormat.samples = 0; + + nsRefPtr glContext = new GLContextOSMesa(actualFormat); if (!glContext->Init(aSize)) { diff --git a/gfx/thebes/GLContextProviderWGL.cpp b/gfx/thebes/GLContextProviderWGL.cpp index 69ae5f1256a9..6edb91c5128f 100644 --- a/gfx/thebes/GLContextProviderWGL.cpp +++ b/gfx/thebes/GLContextProviderWGL.cpp @@ -48,6 +48,8 @@ #include "prenv.h" +#include "mozilla/Preferences.h" + namespace mozilla { namespace gl { @@ -398,10 +400,44 @@ GLContextWGL::UnbindTex2DOffscreen(GLContext *aOffscreen) } } + +static bool +GetMaxSize(HDC hDC, int format, gfxIntSize& size) +{ + int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB}; + int result[2]; + + // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues) + if (!sWGLLibrary.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result)) + return false; + + size.width = result[0]; + size.height = result[1]; + return true; +} + +static bool +IsValidSizeForFormat(HDC hDC, int format, const gfxIntSize& requested) +{ + gfxIntSize max; + if (!GetMaxSize(hDC, format, max)) + return true; + + if (requested.width > max.width) + return false; + if (requested.height > max.height) + return false; + + return true; +} + bool GLContextWGL::ResizeOffscreen(const gfxIntSize& aNewSize) { if (mPBuffer) { + if (!IsValidSizeForFormat(gSharedWindowDC, mPixelFormat, aNewSize)) + return false; + int pbattrs[] = { LOCAL_WGL_TEXTURE_FORMAT_ARB, mCreationFormat.alpha > 0 ? LOCAL_WGL_TEXTURE_RGBA_ARB @@ -433,10 +469,10 @@ GLContextWGL::ResizeOffscreen(const gfxIntSize& aNewSize) MakeCurrent(); ClearSafely(); - return true; + return ResizeOffscreenFBO(aNewSize, false); } - return ResizeOffscreenFBO(aNewSize); + return ResizeOffscreenFBO(aNewSize, true); } static GLContextWGL * @@ -543,6 +579,9 @@ CreatePBufferOffscreenContext(const gfxIntSize& aSize, // XXX add back the priority choosing code here int chosenFormat = formats[0]; + if (!IsValidSizeForFormat(gSharedWindowDC, chosenFormat, aSize)) + return nsnull; + HANDLE pbuffer = sWGLLibrary.fCreatePbuffer(gSharedWindowDC, chosenFormat, aSize.width, aSize.height, pbattrs.Elements()); @@ -570,8 +609,7 @@ CreatePBufferOffscreenContext(const gfxIntSize& aSize, } static already_AddRefed -CreateWindowOffscreenContext(const gfxIntSize& aSize, - const ContextFormat& aFormat) +CreateWindowOffscreenContext(const ContextFormat& aFormat) { // CreateWindowOffscreenContext must return a global-shared context GLContextWGL *shareContext = GetGlobalContextWGL(); @@ -612,19 +650,25 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize, return nsnull; } + ContextFormat actualFormat(aFormat); + // actualFormat.samples = 0; + nsRefPtr glContext; // Always try to create a pbuffer context first, because we // want the context isolation. - if (sWGLLibrary.fCreatePbuffer && + NS_ENSURE_TRUE(Preferences::GetRootBranch(), nsnull); + const bool preferFBOs = Preferences::GetBool("wgl.prefer-fbo", false); + if (!preferFBOs && + sWGLLibrary.fCreatePbuffer && sWGLLibrary.fChoosePixelFormat) { - glContext = CreatePBufferOffscreenContext(aSize, aFormat); + glContext = CreatePBufferOffscreenContext(aSize, actualFormat); } // If it failed, then create a window context and use a FBO. if (!glContext) { - glContext = CreateWindowOffscreenContext(aSize, aFormat); + glContext = CreateWindowOffscreenContext(actualFormat); } if (!glContext || @@ -633,15 +677,12 @@ GLContextProviderWGL::CreateOffscreen(const gfxIntSize& aSize, return nsnull; } + if (!glContext->ResizeOffscreenFBO(aSize, !glContext->mPBuffer)) + return nsnull; + glContext->mOffscreenSize = aSize; glContext->mOffscreenActualSize = aSize; - if (!glContext->mPBuffer && - !glContext->ResizeOffscreenFBO(aSize)) - { - return nsnull; - } - return glContext.forget(); } diff --git a/gfx/thebes/GLContextSymbols.h b/gfx/thebes/GLContextSymbols.h index d53855d372f7..77af7297ac85 100644 --- a/gfx/thebes/GLContextSymbols.h +++ b/gfx/thebes/GLContextSymbols.h @@ -307,6 +307,11 @@ struct GLContextSymbols typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage; + typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFER) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + PFNGLBLITFRAMEBUFFER fBlitFramebuffer; + typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLE) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height); + PFNGLRENDERBUFFERSTORAGEMULTISAMPLE fRenderbufferStorageMultisample; + /* These are different between GLES2 and desktop GL; we hide those differences, use the GL * names, but the most limited data type. diff --git a/js/public/Vector.h b/js/public/Vector.h index d5022d5471ad..eac50701a14c 100644 --- a/js/public/Vector.h +++ b/js/public/Vector.h @@ -560,6 +560,7 @@ Vector::calculateNewCapacity(size_t curLength, size_t lengthInc, size_t &newCap) { size_t newMinCap = curLength + lengthInc; + size_t newMinSize = newMinCap * sizeof(T); /* * Check for overflow in the above addition, below CEILING_LOG2, and later @@ -571,8 +572,14 @@ Vector::calculateNewCapacity(size_t curLength, size_t lengthInc, return false; } - /* Round up to next power of 2. */ - newCap = RoundUpPow2(newMinCap); + /* + * It's best to request 2^N sized chunks because they are unlikely to be + * rounded up by the allocator. (Asking for a 2^N number of elements isn't + * as good, because if sizeof(T) is not a power-of-two that would result in + * a non-2^N request size, which can cause waste.) + */ + size_t newSize = RoundUpPow2(newMinSize); + newCap = newSize / sizeof(T); /* * Do not allow a buffer large enough that the expression ((char *)end() - diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 330901319bd3..b630389b38a3 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -48,25 +48,28 @@ #include "jsinferinlines.h" +using namespace js; +using namespace js::frontend; + namespace js { /* * Compile a top-level script. */ -Compiler::Compiler(JSContext *cx, JSPrincipals *prin, StackFrame *cfp) +BytecodeCompiler::BytecodeCompiler(JSContext *cx, JSPrincipals *prin, StackFrame *cfp) : parser(cx, prin, cfp), globalScope(NULL) {} JSScript * -Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame, - JSPrincipals *principals, uint32 tcflags, - const jschar *chars, size_t length, - const char *filename, uintN lineno, JSVersion version, - JSString *source /* = NULL */, - uintN staticLevel /* = 0 */) +BytecodeCompiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame, + JSPrincipals *principals, uint32 tcflags, + const jschar *chars, size_t length, + const char *filename, uintN lineno, JSVersion version, + JSString *source /* = NULL */, + uintN staticLevel /* = 0 */) { TokenKind tt; - JSParseNode *pn; + ParseNode *pn; JSScript *script; bool inDirectivePrologue; @@ -80,15 +83,15 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO); JS_ASSERT_IF(staticLevel != 0, callerFrame); - Compiler compiler(cx, principals, callerFrame); + BytecodeCompiler compiler(cx, principals, callerFrame); if (!compiler.init(chars, length, filename, lineno, version)) return NULL; Parser &parser = compiler.parser; TokenStream &tokenStream = parser.tokenStream; - JSCodeGenerator cg(&parser, tokenStream.getLineno()); - if (!cg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT)) + CodeGenerator cg(&parser, tokenStream.getLineno()); + if (!cg.init(cx, TreeContext::USED_AS_TREE_CONTEXT)) return NULL; Probes::compileScriptBegin(cx, filename, lineno); @@ -143,7 +146,7 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF * function captured in case it refers to an upvar, and someone * wishes to decompile it while it's running. */ - JSObjectBox *funbox = parser.newObjectBox(callerFrame->fun()); + ObjectBox *funbox = parser.newObjectBox(callerFrame->fun()); if (!funbox) goto out; funbox->emitLink = cg.objectList.lastbox; @@ -189,21 +192,21 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF if (inDirectivePrologue && !parser.recognizeDirectivePrologue(pn, &inDirectivePrologue)) goto out; - if (!js_FoldConstants(cx, pn, &cg)) + if (!FoldConstants(cx, pn, &cg)) goto out; if (!parser.analyzeFunctions(&cg)) goto out; cg.functionList = NULL; - if (!js_EmitTree(cx, &cg, pn)) + if (!EmitTree(cx, &cg, pn)) goto out; #if JS_HAS_XML_SUPPORT if (!pn->isKind(TOK_SEMI) || !pn->pn_kid || !TreeTypeIsXML(pn->pn_kid->getKind())) onlyXML = false; #endif - RecycleTree(pn, &cg); + cg.freeTree(pn); } #if JS_HAS_XML_SUPPORT @@ -257,7 +260,7 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF * Nowadays the threaded interpreter needs a stop instruction, so we * do have to emit that here. */ - if (js_Emit1(cx, &cg, JSOP_STOP) < 0) + if (Emit1(cx, &cg, JSOP_STOP) < 0) goto out; JS_ASSERT(cg.version() == version); @@ -282,7 +285,7 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF } bool -Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script) +BytecodeCompiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *script) { JSObject *globalObj = globalScope.globalObj; @@ -325,7 +328,7 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip def.knownSlot = shape->slot; } - js::Vector worklist(cx); + Vector worklist(cx); if (!worklist.append(script)) return false; @@ -388,11 +391,11 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip * handler attribute in an HTML tag. */ bool -Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals, - Bindings *bindings, const jschar *chars, size_t length, - const char *filename, uintN lineno, JSVersion version) +BytecodeCompiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals, + Bindings *bindings, const jschar *chars, size_t length, + const char *filename, uintN lineno, JSVersion version) { - Compiler compiler(cx, principals); + BytecodeCompiler compiler(cx, principals); if (!compiler.init(chars, length, filename, lineno, version)) return false; @@ -400,8 +403,8 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin Parser &parser = compiler.parser; TokenStream &tokenStream = parser.tokenStream; - JSCodeGenerator funcg(&parser, tokenStream.getLineno()); - if (!funcg.init(cx, JSTreeContext::USED_AS_TREE_CONTEXT)) + CodeGenerator funcg(&parser, tokenStream.getLineno()); + if (!funcg.init(cx, TreeContext::USED_AS_TREE_CONTEXT)) return false; funcg.flags |= TCF_IN_FUNCTION; @@ -413,7 +416,7 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin /* FIXME: make Function format the source for a function definition. */ tokenStream.mungeCurrentToken(TOK_NAME); - JSParseNode *fn = FunctionNode::create(&funcg); + ParseNode *fn = FunctionNode::create(&funcg); if (fn) { fn->pn_body = NULL; fn->pn_cookie.makeFree(); @@ -439,21 +442,22 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin } /* - * Farble the body so that it looks like a block statement to js_EmitTree, - * which is called from js_EmitFunctionBody (see jsemit.cpp). After we're - * done parsing, we must fold constants, analyze any nested functions, and - * generate code for this function, including a stop opcode at the end. + * Farble the body so that it looks like a block statement to EmitTree, + * which is called from EmitFunctionBody (see BytecodeGenerator.cpp). + * After we're done parsing, we must fold constants, analyze any nested + * functions, and generate code for this function, including a stop opcode + * at the end. */ tokenStream.mungeCurrentToken(TOK_LC); - JSParseNode *pn = fn ? parser.functionBody() : NULL; + ParseNode *pn = fn ? parser.functionBody() : NULL; if (pn) { if (!CheckStrictParameters(cx, &funcg)) { pn = NULL; } else if (!tokenStream.matchToken(TOK_EOF)) { parser.reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR); pn = NULL; - } else if (!js_FoldConstants(cx, pn, &funcg)) { - /* js_FoldConstants reported the error already. */ + } else if (!FoldConstants(cx, pn, &funcg)) { + /* FoldConstants reported the error already. */ pn = NULL; } else if (!parser.analyzeFunctions(&funcg)) { pn = NULL; @@ -465,7 +469,7 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin pn = fn->pn_body; } - if (!js_EmitFunctionScript(cx, &funcg, pn)) + if (!EmitFunctionScript(cx, &funcg, pn)) pn = NULL; } } diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index fcb198acf910..ca7c51836de6 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -45,12 +45,12 @@ namespace js { -struct Compiler +struct BytecodeCompiler { Parser parser; GlobalScope *globalScope; - Compiler(JSContext *cx, JSPrincipals *prin = NULL, StackFrame *cfp = NULL); + BytecodeCompiler(JSContext *cx, JSPrincipals *prin = NULL, StackFrame *cfp = NULL); JSContext *context() { return parser.context; @@ -63,7 +63,7 @@ struct Compiler static bool compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals, - js::Bindings *bindings, const jschar *chars, size_t length, + Bindings *bindings, const jschar *chars, size_t length, const char *filename, uintN lineno, JSVersion version); static JSScript * diff --git a/js/src/frontend/BytecodeGenerator.cpp b/js/src/frontend/BytecodeGenerator.cpp index 94507cf0e143..c30171e2915e 100644 --- a/js/src/frontend/BytecodeGenerator.cpp +++ b/js/src/frontend/BytecodeGenerator.cpp @@ -87,26 +87,35 @@ using namespace js; using namespace js::gc; +using namespace js::frontend; + +#ifdef JS_TRACER +extern uint8 js_opcode2extra[]; +#endif + +namespace js { +namespace frontend { static JSBool -NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind, - uintN stackDepth, size_t start, size_t end); +NewTryNote(JSContext *cx, CodeGenerator *cg, JSTryNoteKind kind, uintN stackDepth, + size_t start, size_t end); static bool -EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg, - JSOp *psuffix = NULL); +EmitIndexOp(JSContext *cx, JSOp op, uintN index, CodeGenerator *cg, JSOp *psuffix = NULL); static JSBool -EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, JSObjectBox *box); +EmitLeaveBlock(JSContext *cx, CodeGenerator *cg, JSOp op, ObjectBox *box); + +} /* namespace frontend */ void -JSTreeContext::trace(JSTracer *trc) +TreeContext::trace(JSTracer *trc) { bindings.trace(trc); } -JSCodeGenerator::JSCodeGenerator(Parser *parser, uintN lineno) - : JSTreeContext(parser), +CodeGenerator::CodeGenerator(Parser *parser, uintN lineno) + : TreeContext(parser), atomIndices(parser->context), stackDepth(0), maxStackDepth(0), ntrynotes(0), lastTryNode(NULL), @@ -133,13 +142,13 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser, uintN lineno) } bool -JSCodeGenerator::init(JSContext *cx, JSTreeContext::InitBehavior ib) +CodeGenerator::init(JSContext *cx, TreeContext::InitBehavior ib) { roLexdeps.init(); - return JSTreeContext::init(cx, ib) && constMap.init() && atomIndices.ensureMap(cx); + return TreeContext::init(cx, ib) && constMap.init() && atomIndices.ensureMap(cx); } -JSCodeGenerator::~JSCodeGenerator() +CodeGenerator::~CodeGenerator() { JSContext *cx = parser->context; @@ -153,8 +162,10 @@ JSCodeGenerator::~JSCodeGenerator() cx->free_(spanDeps); } +namespace frontend { + static ptrdiff_t -EmitCheck(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t delta) +EmitCheck(JSContext *cx, CodeGenerator *cg, ptrdiff_t delta) { jsbytecode *base = CG_BASE(cg); jsbytecode *newbase; @@ -191,7 +202,7 @@ EmitCheck(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t delta) } static void -UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target) +UpdateDepth(JSContext *cx, CodeGenerator *cg, ptrdiff_t target) { jsbytecode *pc; JSOp op; @@ -203,7 +214,6 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target) op = (JSOp) *pc; cs = &js_CodeSpec[op]; #ifdef JS_TRACER - extern uint8 js_opcode2extra[]; extra = js_opcode2extra[op]; #else extra = 0; @@ -251,7 +261,7 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target) } static inline void -UpdateDecomposeLength(JSCodeGenerator *cg, uintN start) +UpdateDecomposeLength(CodeGenerator *cg, uintN start) { uintN end = CG_OFFSET(cg); JS_ASSERT(uintN(end - start) < 256); @@ -259,7 +269,7 @@ UpdateDecomposeLength(JSCodeGenerator *cg, uintN start) } ptrdiff_t -js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op) +Emit1(JSContext *cx, CodeGenerator *cg, JSOp op) { ptrdiff_t offset = EmitCheck(cx, cg, 1); @@ -271,7 +281,7 @@ js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op) } ptrdiff_t -js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1) +Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1) { ptrdiff_t offset = EmitCheck(cx, cg, 2); @@ -286,7 +296,7 @@ js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1) } ptrdiff_t -js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1, +Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1, jsbytecode op2) { ptrdiff_t offset = EmitCheck(cx, cg, 3); @@ -303,7 +313,7 @@ js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1, } ptrdiff_t -js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1, uint16 op2) +Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2) { ptrdiff_t offset = EmitCheck(cx, cg, 5); @@ -321,7 +331,7 @@ js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1, uint16 op2) } ptrdiff_t -js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra) +EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra) { ptrdiff_t length = 1 + (ptrdiff_t)extra; ptrdiff_t offset = EmitCheck(cx, cg, length); @@ -368,7 +378,7 @@ static const char *statementName[] = { JS_STATIC_ASSERT(JS_ARRAY_LENGTH(statementName) == STMT_LIMIT); static const char * -StatementName(JSCodeGenerator *cg) +StatementName(CodeGenerator *cg) { if (!cg->topStmt) return js_script_str; @@ -376,7 +386,7 @@ StatementName(JSCodeGenerator *cg) } static void -ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg) +ReportStatementTooLarge(JSContext *cx, CodeGenerator *cg) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, StatementName(cg)); @@ -405,19 +415,19 @@ ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg) case by generating short jumps until we know a long jump is needed. After that point, we keep generating short jumps, but each jump's 16-bit immediate offset operand is actually an unsigned index into cg->spanDeps, an array of - JSSpanDep structs. Each struct tells the top offset in the script of the + js::SpanDep structs. Each struct tells the top offset in the script of the opcode, the "before" offset of the jump (which will be the same as top for simplex jumps, but which will index further into the bytecode array for a non-initial jump offset in a lookup or table switch), the after "offset" adjusted during span-dependent instruction selection (initially the same value as the "before" offset), and the jump target (more below). - Since we generate cg->spanDeps lazily, from within js_SetJumpOffset, we must + Since we generate cg->spanDeps lazily, from within SetJumpOffset, we must ensure that all bytecode generated so far can be inspected to discover where the jump offset immediate operands lie within CG_CODE(cg). But the bonus is that we generate span-dependency records sorted by their offsets, so we can - binary-search when trying to find a JSSpanDep for a given bytecode offset, - or the nearest JSSpanDep at or above a given pc. + binary-search when trying to find a SpanDep for a given bytecode offset, or + the nearest SpanDep at or above a given pc. To avoid limiting scripts to 64K jumps, if the cg->spanDeps index overflows 65534, we store SPANDEP_INDEX_HUGE in the jump's immediate operand. This @@ -436,8 +446,8 @@ ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg) positive sign, even though they link "backward" (i.e., toward lower bytecode address). We don't want to waste space and search time in the AVL tree for such temporary backpatch deltas, so we use a single-bit wildcard scheme to - tag true JSJumpTarget pointers and encode untagged, signed (positive) deltas - in JSSpanDep.target pointers, depending on whether the JSSpanDep has a known + tag true JumpTarget pointers and encode untagged, signed (positive) deltas in + SpanDep::target pointers, depending on whether the SpanDep has a known target, or is still awaiting backpatching. Note that backpatch chains would present a problem for BuildSpanDepTable, @@ -449,15 +459,13 @@ ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg) offset. */ static int -BalanceJumpTargets(JSJumpTarget **jtp) +BalanceJumpTargets(JumpTarget **jtp) { - JSJumpTarget *jt, *jt2, *root; - int dir, otherDir, heightChanged; - JSBool doubleRotate; - - jt = *jtp; + JumpTarget *jt = *jtp; JS_ASSERT(jt->balance != 0); + int dir; + JSBool doubleRotate; if (jt->balance < -1) { dir = JT_RIGHT; doubleRotate = (jt->kids[JT_LEFT]->balance > 0); @@ -468,9 +476,11 @@ BalanceJumpTargets(JSJumpTarget **jtp) return 0; } - otherDir = JT_OTHER_DIR(dir); + int otherDir = JT_OTHER_DIR(dir); + JumpTarget *root; + int heightChanged; if (doubleRotate) { - jt2 = jt->kids[otherDir]; + JumpTarget *jt2 = jt->kids[otherDir]; *jtp = root = jt2->kids[dir]; jt->kids[otherDir] = root->kids[dir]; @@ -495,28 +505,25 @@ BalanceJumpTargets(JSJumpTarget **jtp) return heightChanged; } -typedef struct AddJumpTargetArgs { +struct AddJumpTargetArgs { JSContext *cx; - JSCodeGenerator *cg; + CodeGenerator *cg; ptrdiff_t offset; - JSJumpTarget *node; -} AddJumpTargetArgs; + JumpTarget *node; +}; static int -AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp) +AddJumpTarget(AddJumpTargetArgs *args, JumpTarget **jtp) { - JSJumpTarget *jt; - int balanceDelta; - - jt = *jtp; + JumpTarget *jt = *jtp; if (!jt) { - JSCodeGenerator *cg = args->cg; + CodeGenerator *cg = args->cg; jt = cg->jtFreeList; if (jt) { cg->jtFreeList = jt->kids[JT_LEFT]; } else { - jt = args->cx->tempLifoAlloc().new_(); + jt = args->cx->tempLifoAlloc().new_(); if (!jt) { js_ReportOutOfMemory(args->cx); return 0; @@ -536,6 +543,7 @@ AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp) return 0; } + int balanceDelta; if (args->offset < jt->offset) balanceDelta = -AddJumpTarget(args, &jt->kids[JT_LEFT]); else @@ -550,7 +558,7 @@ AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp) } #ifdef DEBUG_brendan -static int AVLCheck(JSJumpTarget *jt) +static int AVLCheck(JumpTarget *jt) { int lh, rh; @@ -564,8 +572,7 @@ static int AVLCheck(JSJumpTarget *jt) #endif static JSBool -SetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd, - ptrdiff_t off) +SetSpanDepTarget(JSContext *cx, CodeGenerator *cg, SpanDep *sd, ptrdiff_t off) { AddJumpTargetArgs args; @@ -591,34 +598,31 @@ SetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd, } #define SPANDEPS_MIN 256 -#define SPANDEPS_SIZE(n) ((n) * sizeof(JSSpanDep)) +#define SPANDEPS_SIZE(n) ((n) * sizeof(js::SpanDep)) #define SPANDEPS_SIZE_MIN SPANDEPS_SIZE(SPANDEPS_MIN) static JSBool -AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, - ptrdiff_t off) +AddSpanDep(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, ptrdiff_t off) { - uintN index; - JSSpanDep *sdbase, *sd; - size_t size; - - index = cg->numSpanDeps; + uintN index = cg->numSpanDeps; if (index + 1 == 0) { ReportStatementTooLarge(cx, cg); return JS_FALSE; } + SpanDep *sdbase; if ((index & (index - 1)) == 0 && - (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) { - size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2; - sdbase = (JSSpanDep *) cx->realloc_(sdbase, size + size); + (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) + { + size_t size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2; + sdbase = (SpanDep *) cx->realloc_(sdbase, size + size); if (!sdbase) return JS_FALSE; cg->spanDeps = sdbase; } cg->numSpanDeps = index + 1; - sd = cg->spanDeps + index; + SpanDep *sd = cg->spanDeps + index; sd->top = pc - CG_BASE(cg); sd->offset = sd->before = pc2 - CG_BASE(cg); @@ -648,7 +652,7 @@ AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2, } static jsbytecode * -AddSwitchSpanDeps(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc) +AddSwitchSpanDeps(JSContext *cx, CodeGenerator *cg, jsbytecode *pc) { JSOp op; jsbytecode *pc2; @@ -687,7 +691,7 @@ AddSwitchSpanDeps(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc) } static JSBool -BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg) +BuildSpanDepTable(JSContext *cx, CodeGenerator *cg) { jsbytecode *pc, *end; JSOp op; @@ -723,13 +727,13 @@ BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg) return JS_TRUE; } -static JSSpanDep * -GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc) +static SpanDep * +GetSpanDep(CodeGenerator *cg, jsbytecode *pc) { uintN index; ptrdiff_t offset; int lo, hi, mid; - JSSpanDep *sd; + SpanDep *sd; index = GET_SPANDEP_INDEX(pc); if (index != SPANDEP_INDEX_HUGE) @@ -754,10 +758,9 @@ GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc) } static JSBool -SetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t delta) +SetBackPatchDelta(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t delta) { - JSSpanDep *sd; + SpanDep *sd; JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN); if (!cg->spanDeps && delta < JUMP_OFFSET_MAX) { @@ -780,7 +783,7 @@ SetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, } static void -UpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta) +UpdateJumpTargets(JumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta) { if (jt->offset > pivot) { jt->offset += delta; @@ -791,20 +794,16 @@ UpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta) UpdateJumpTargets(jt->kids[JT_RIGHT], pivot, delta); } -static JSSpanDep * -FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo, - JSSpanDep *guard) +static SpanDep * +FindNearestSpanDep(CodeGenerator *cg, ptrdiff_t offset, int lo, SpanDep *guard) { - int num, hi, mid; - JSSpanDep *sdbase, *sd; - - num = cg->numSpanDeps; + int num = cg->numSpanDeps; JS_ASSERT(num > 0); - hi = num - 1; - sdbase = cg->spanDeps; + int hi = num - 1; + SpanDep *sdbase = cg->spanDeps; while (lo <= hi) { - mid = (lo + hi) / 2; - sd = sdbase + mid; + int mid = (lo + hi) / 2; + SpanDep *sd = sdbase + mid; if (sd->before == offset) return sd; if (sd->before < offset) @@ -814,13 +813,13 @@ FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo, } if (lo == num) return guard; - sd = sdbase + lo; + SpanDep *sd = sdbase + lo; JS_ASSERT(sd->before >= offset && (lo == 0 || sd[-1].before < offset)); return sd; } static void -FreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt) +FreeJumpTargets(CodeGenerator *cg, JumpTarget *jt) { if (jt->kids[JT_LEFT]) FreeJumpTargets(cg, jt->kids[JT_LEFT]); @@ -831,10 +830,10 @@ FreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt) } static JSBool -OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) +OptimizeSpanDeps(JSContext *cx, CodeGenerator *cg) { jsbytecode *pc, *oldpc, *base, *limit, *next; - JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard; + SpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard; ptrdiff_t offset, growth, delta, top, pivot, span, length, target; JSBool done; JSOp op; @@ -842,7 +841,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) jssrcnote *sn, *snlimit; JSSrcNoteSpec *spec; uintN i, n, noteIndex; - JSTryNode *tryNode; + TryNode *tryNode; DebugOnly passes = 0; base = CG_BASE(cg); @@ -1092,7 +1091,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) delta = sd2->offset - (sd2->before + growth); if (delta > 0) { JS_ASSERT(delta == JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN); - sn = js_AddToSrcNoteDelta(cx, cg, sn, delta); + sn = AddToSrcNoteDelta(cx, cg, sn, delta); if (!sn) return JS_FALSE; snlimit = cg->main.notes + cg->main.noteCount; @@ -1134,7 +1133,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) span = target - (pivot + growth); span *= spec->isSpanDep; noteIndex = sn - cg->main.notes; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, i, span)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, i, span)) return JS_FALSE; sn = cg->main.notes + noteIndex; snlimit = cg->main.notes + cg->main.noteCount; @@ -1230,7 +1229,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) } static ptrdiff_t -EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off) +EmitJump(JSContext *cx, CodeGenerator *cg, JSOp op, ptrdiff_t off) { JSBool extend; ptrdiff_t jmp; @@ -1240,7 +1239,7 @@ EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off) if (extend && !cg->spanDeps && !BuildSpanDepTable(cx, cg)) return -1; - jmp = js_Emit3(cx, cg, op, JUMP_OFFSET_HI(off), JUMP_OFFSET_LO(off)); + jmp = Emit3(cx, cg, op, JUMP_OFFSET_HI(off), JUMP_OFFSET_LO(off)); if (jmp >= 0 && (extend || cg->spanDeps)) { pc = CG_CODE(cg, jmp); if (!AddSpanDep(cx, cg, pc, pc, off)) @@ -1250,21 +1249,17 @@ EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off) } static ptrdiff_t -GetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc) +GetJumpOffset(CodeGenerator *cg, jsbytecode *pc) { - JSSpanDep *sd; - JSJumpTarget *jt; - ptrdiff_t top; - if (!cg->spanDeps) return GET_JUMP_OFFSET(pc); - sd = GetSpanDep(cg, pc); - jt = sd->target; + SpanDep *sd = GetSpanDep(cg, pc); + JumpTarget *jt = sd->target; if (!JT_HAS_TAG(jt)) return JT_TO_BPDELTA(jt); - top = sd->top; + ptrdiff_t top = sd->top; while (--sd >= cg->spanDeps && sd->top == top) continue; sd++; @@ -1272,8 +1267,7 @@ GetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc) } JSBool -js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t off) +SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off) { if (!cg->spanDeps) { if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) { @@ -1288,10 +1282,12 @@ js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off); } +} /* namespace frontend */ + bool -JSTreeContext::inStatement(JSStmtType type) +TreeContext::inStatement(StmtType type) { - for (JSStmtInfo *stmt = topStmt; stmt; stmt = stmt->down) { + for (StmtInfo *stmt = topStmt; stmt; stmt = stmt->down) { if (stmt->type == type) return true; } @@ -1299,7 +1295,7 @@ JSTreeContext::inStatement(JSStmtType type) } bool -JSTreeContext::ensureSharpSlots() +TreeContext::ensureSharpSlots() { #if JS_HAS_SHARP_VARS JS_STATIC_ASSERT(SHARP_NSLOTS == 2); @@ -1324,9 +1320,9 @@ JSTreeContext::ensureSharpSlots() return false; } else { /* - * Compiler::compileScript will rebase immediate operands indexing - * the sharp slots to come at the end of the global script's |nfixed| - * slots storage, after gvars and regexps. + * BytecodeCompiler::compileScript will rebase immediate operands + * indexing the sharp slots to come at the end of the global script's + * |nfixed| slots storage, after gvars and regexps. */ sharpSlotBase = 0; } @@ -1336,9 +1332,9 @@ JSTreeContext::ensureSharpSlots() } bool -JSTreeContext::skipSpansGenerator(unsigned skip) +TreeContext::skipSpansGenerator(unsigned skip) { - JSTreeContext *tc = this; + TreeContext *tc = this; for (unsigned i = 0; i < skip; ++i, tc = tc->parent) { if (!tc) return false; @@ -1348,10 +1344,10 @@ JSTreeContext::skipSpansGenerator(unsigned skip) return false; } -namespace js { +namespace frontend { bool -SetStaticLevel(JSTreeContext *tc, uintN staticLevel) +SetStaticLevel(TreeContext *tc, uintN staticLevel) { /* * This is a lot simpler than error-checking every UpvarCookie::set, and @@ -1367,7 +1363,7 @@ SetStaticLevel(JSTreeContext *tc, uintN staticLevel) } bool -GenerateBlockId(JSTreeContext *tc, uint32& blockid) +GenerateBlockId(TreeContext *tc, uint32& blockid) { if (tc->blockidGen == JS_BIT(20)) { JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL, @@ -1378,11 +1374,8 @@ GenerateBlockId(JSTreeContext *tc, uint32& blockid) return true; } -} /* namespace js */ - void -js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type, - ptrdiff_t top) +PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top) { stmt->type = type; stmt->flags = 0; @@ -1401,10 +1394,9 @@ js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type, } void -js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObjectBox *blockBox, - ptrdiff_t top) +PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top) { - js_PushStatement(tc, stmt, STMT_BLOCK, top); + PushStatement(tc, stmt, STMT_BLOCK, top); stmt->flags |= SIF_SCOPE; blockBox->parent = tc->blockChainBox; blockBox->object->setParent(tc->blockChain()); @@ -1419,7 +1411,7 @@ js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObjectBox *blockBox, * so that we can walk back up the chain fixing up the op and jump offset. */ static ptrdiff_t -EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp) +EmitBackPatchOp(JSContext *cx, CodeGenerator *cg, JSOp op, ptrdiff_t *lastp) { ptrdiff_t offset, delta; @@ -1430,7 +1422,7 @@ EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp) return EmitJump(cx, cg, op, delta); } -/* A macro for inlining at the top of js_EmitTree (whence it came). */ +/* A macro for inlining at the top of EmitTree (whence it came). */ #define UPDATE_LINE_NUMBER_NOTES(cx, cg, line) \ JS_BEGIN_MACRO \ uintN line_ = (line); \ @@ -1449,11 +1441,11 @@ EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp) */ \ CG_CURRENT_LINE(cg) = line_; \ if (delta_ >= (uintN)(2 + ((line_ > SN_3BYTE_OFFSET_MASK)<<1))) { \ - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)line_) < 0)\ + if (NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)line_) < 0) \ return JS_FALSE; \ } else { \ do { \ - if (js_NewSrcNote(cx, cg, SRC_NEWLINE) < 0) \ + if (NewSrcNote(cx, cg, SRC_NEWLINE) < 0) \ return JS_FALSE; \ } while (--delta_ != 0); \ } \ @@ -1462,14 +1454,14 @@ EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp) /* A function, so that we avoid macro-bloating all the other callsites. */ static JSBool -UpdateLineNumberNotes(JSContext *cx, JSCodeGenerator *cg, uintN line) +UpdateLineNumberNotes(JSContext *cx, CodeGenerator *cg, uintN line) { UPDATE_LINE_NUMBER_NOTES(cx, cg, line); return JS_TRUE; } static ptrdiff_t -EmitTraceOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *nextpn) +EmitTraceOp(JSContext *cx, CodeGenerator *cg, ParseNode *nextpn) { if (nextpn) { /* @@ -1486,7 +1478,7 @@ EmitTraceOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *nextpn) uint32 index = cg->traceIndex; if (index < UINT16_MAX) cg->traceIndex++; - return js_Emit3(cx, cg, JSOP_TRACE, UINT16_HI(index), UINT16_LO(index)); + return Emit3(cx, cg, JSOP_TRACE, UINT16_HI(index), UINT16_LO(index)); } /* @@ -1494,7 +1486,7 @@ EmitTraceOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *nextpn) * a type set to store its result. */ static inline void -CheckTypeSet(JSContext *cx, JSCodeGenerator *cg, JSOp op) +CheckTypeSet(JSContext *cx, CodeGenerator *cg, JSOp op) { if (js_CodeSpec[op].format & JOF_TYPESET) { if (cg->typesetCount < UINT16_MAX) @@ -1510,14 +1502,14 @@ CheckTypeSet(JSContext *cx, JSCodeGenerator *cg, JSOp op) */ #define EMIT_UINT16_IMM_OP(op, i) \ JS_BEGIN_MACRO \ - if (js_Emit3(cx, cg, op, UINT16_HI(i), UINT16_LO(i)) < 0) \ + if (Emit3(cx, cg, op, UINT16_HI(i), UINT16_LO(i)) < 0) \ return JS_FALSE; \ CheckTypeSet(cx, cg, op); \ JS_END_MACRO #define EMIT_UINT16PAIR_IMM_OP(op, i, j) \ JS_BEGIN_MACRO \ - ptrdiff_t off_ = js_EmitN(cx, cg, op, 2 * UINT16_LEN); \ + ptrdiff_t off_ = EmitN(cx, cg, op, 2 * UINT16_LEN); \ if (off_ < 0) \ return JS_FALSE; \ jsbytecode *pc_ = CG_CODE(cg, off_); \ @@ -1534,10 +1526,10 @@ CheckTypeSet(JSContext *cx, JSCodeGenerator *cg, JSOp op) JS_END_MACRO static JSBool -FlushPops(JSContext *cx, JSCodeGenerator *cg, intN *npops) +FlushPops(JSContext *cx, CodeGenerator *cg, intN *npops) { JS_ASSERT(*npops != 0); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; EMIT_UINT16_IMM_OP(JSOP_POPN, *npops); *npops = 0; @@ -1548,27 +1540,24 @@ FlushPops(JSContext *cx, JSCodeGenerator *cg, intN *npops) * Emit additional bytecode(s) for non-local jumps. */ static JSBool -EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt) +EmitNonLocalJumpFixup(JSContext *cx, CodeGenerator *cg, StmtInfo *toStmt) { - intN depth, npops; - JSStmtInfo *stmt; - /* * The non-local jump fixup we emit will unbalance cg->stackDepth, because * the fixup replicates balanced code such as JSOP_LEAVEWITH emitted at the * end of a with statement, so we save cg->stackDepth here and restore it * just before a successful return. */ - depth = cg->stackDepth; - npops = 0; + intN depth = cg->stackDepth; + intN npops = 0; #define FLUSH_POPS() if (npops && !FlushPops(cx, cg, &npops)) return JS_FALSE - for (stmt = cg->topStmt; stmt != toStmt; stmt = stmt->down) { + for (StmtInfo *stmt = cg->topStmt; stmt != toStmt; stmt = stmt->down) { switch (stmt->type) { case STMT_FINALLY: FLUSH_POPS(); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(*stmt)) < 0) return JS_FALSE; @@ -1577,9 +1566,9 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt) case STMT_WITH: /* There's a With object on the stack that we need to pop. */ FLUSH_POPS(); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) + if (Emit1(cx, cg, JSOP_LEAVEWITH) < 0) return JS_FALSE; break; @@ -1588,9 +1577,9 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt) * The iterator and the object being iterated need to be popped. */ FLUSH_POPS(); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_ENDITER) < 0) + if (Emit1(cx, cg, JSOP_ENDITER) < 0) return JS_FALSE; break; @@ -1608,7 +1597,7 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt) if (stmt->flags & SIF_SCOPE) { /* There is a Block object with locals on the stack to pop. */ FLUSH_POPS(); - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; if (!EmitLeaveBlock(cx, cg, JSOP_LEAVEBLOCK, stmt->blockBox)) return JS_FALSE; @@ -1623,15 +1612,15 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt) } static JSBool -EmitKnownBlockChain(JSContext *cx, JSCodeGenerator *cg, JSObjectBox *box) +EmitKnownBlockChain(JSContext *cx, CodeGenerator *cg, ObjectBox *box) { if (box) return EmitIndexOp(cx, JSOP_BLOCKCHAIN, box->index, cg); - return js_Emit1(cx, cg, JSOP_NULLBLOCKCHAIN) >= 0; + return Emit1(cx, cg, JSOP_NULLBLOCKCHAIN) >= 0; } static JSBool -EmitBlockChain(JSContext *cx, JSCodeGenerator *cg) +EmitBlockChain(JSContext *cx, CodeGenerator *cg) { return EmitKnownBlockChain(cx, cg, cg->blockChainBox); } @@ -1639,8 +1628,8 @@ EmitBlockChain(JSContext *cx, JSCodeGenerator *cg) static const jsatomid INVALID_ATOMID = -1; static ptrdiff_t -EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt, - ptrdiff_t *lastp, jsatomid labelIndex = INVALID_ATOMID, JSSrcNoteType noteType = SRC_NULL) +EmitGoto(JSContext *cx, CodeGenerator *cg, StmtInfo *toStmt, ptrdiff_t *lastp, + jsatomid labelIndex = INVALID_ATOMID, SrcNoteType noteType = SRC_NULL) { intN index; @@ -1648,9 +1637,9 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt, return -1; if (labelIndex != INVALID_ATOMID) - index = js_NewSrcNote2(cx, cg, noteType, ptrdiff_t(labelIndex)); + index = NewSrcNote2(cx, cg, noteType, ptrdiff_t(labelIndex)); else if (noteType != SRC_NULL) - index = js_NewSrcNote(cx, cg, noteType); + index = NewSrcNote(cx, cg, noteType); else index = 0; if (index < 0) @@ -1667,8 +1656,7 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt, } static JSBool -BackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last, - jsbytecode *target, jsbytecode op) +BackPatch(JSContext *cx, CodeGenerator *cg, ptrdiff_t last, jsbytecode *target, jsbytecode op) { jsbytecode *pc, *stop; ptrdiff_t delta, span; @@ -1692,11 +1680,9 @@ BackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last, } void -js_PopStatement(JSTreeContext *tc) +PopStatementTC(TreeContext *tc) { - JSStmtInfo *stmt; - - stmt = tc->topStmt; + StmtInfo *stmt = tc->topStmt; tc->topStmt = stmt->down; if (STMT_LINKS_SCOPE(stmt)) { tc->topScopeStmt = stmt->downScope; @@ -1707,24 +1693,21 @@ js_PopStatement(JSTreeContext *tc) } JSBool -js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg) +PopStatementCG(JSContext *cx, CodeGenerator *cg) { - JSStmtInfo *stmt; - - stmt = cg->topStmt; + StmtInfo *stmt = cg->topStmt; if (!STMT_IS_TRYING(stmt) && (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) || !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update), JSOP_GOTO))) { return JS_FALSE; } - js_PopStatement(cg); + PopStatementTC(cg); return JS_TRUE; } JSBool -js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - JSParseNode *pn) +DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn) { /* XXX just do numbers for now */ if (pn->isKind(TOK_NUMBER)) { @@ -1734,8 +1717,8 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, return JS_TRUE; } -JSStmtInfo * -js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt) +StmtInfo * +LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt) { if (!stmt) stmt = tc->topScopeStmt; @@ -1772,12 +1755,8 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt * name defining a constant. */ static JSBool -LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - Value *constp) +LookupCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, Value *constp) { - JSStmtInfo *stmt; - JSObject *obj; - /* * Chase down the cg stack, but only until we reach the outermost cg. * This enables propagating consts from top-level into switch cases in a @@ -1787,11 +1766,11 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, do { if (cg->inFunction() || cg->compileAndGo()) { /* XXX this will need revising if 'const' becomes block-scoped. */ - stmt = js_LexicalLookup(cg, atom, NULL); + StmtInfo *stmt = LexicalLookup(cg, atom, NULL); if (stmt) return JS_TRUE; - if (JSCodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) { + if (CodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) { JS_ASSERT(!p->value.isMagic(JS_NO_CONSTANT)); *constp = p->value; return JS_TRUE; @@ -1809,7 +1788,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, break; } else { JS_ASSERT(cg->compileAndGo()); - obj = cg->scopeChain(); + JSObject *obj = cg->scopeChain(); const Shape *shape = obj->nativeLookup(cx, ATOM_TO_JSID(atom)); if (shape) { @@ -1846,7 +1825,7 @@ FitsWithoutBigIndex(uintN index) * after the main bytecode sequence. */ static JSOp -EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index) +EmitBigIndexPrefix(JSContext *cx, CodeGenerator *cg, uintN index) { uintN indexBase; @@ -1862,7 +1841,7 @@ EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index) return JSOP_NOP; indexBase = index >> 16; if (indexBase <= JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 1) { - if (js_Emit1(cx, cg, (JSOp)(JSOP_INDEXBASE1 + indexBase - 1)) < 0) + if (Emit1(cx, cg, (JSOp)(JSOP_INDEXBASE1 + indexBase - 1)) < 0) return JSOP_FALSE; return JSOP_RESETBASE0; } @@ -1873,7 +1852,7 @@ EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index) return JSOP_FALSE; } - if (js_Emit2(cx, cg, JSOP_INDEXBASE, (JSOp)indexBase) < 0) + if (Emit2(cx, cg, JSOP_INDEXBASE, (JSOp)indexBase) < 0) return JSOP_FALSE; return JSOP_RESETBASE; } @@ -1889,7 +1868,7 @@ EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index) * register setting, but this could be optimized further. */ static bool -EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg, JSOp *psuffix) +EmitIndexOp(JSContext *cx, JSOp op, uintN index, CodeGenerator *cg, JSOp *psuffix) { JSOp bigSuffix; @@ -1909,7 +1888,7 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg, JSOp *psuf return true; } - return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0; + return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0; } /* @@ -1923,8 +1902,7 @@ EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg, JSOp *psuf JS_END_MACRO static bool -EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, - JSOp *psuffix = NULL) +EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg, JSOp *psuffix = NULL) { JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM); @@ -1942,8 +1920,7 @@ EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, } static JSBool -EmitObjectOp(JSContext *cx, JSObjectBox *objbox, JSOp op, - JSCodeGenerator *cg) +EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, CodeGenerator *cg) { JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT); return EmitIndexOp(cx, op, cg->objectList.index(objbox), cg); @@ -1960,8 +1937,7 @@ JS_STATIC_ASSERT(ARGNO_LEN == 2); JS_STATIC_ASSERT(SLOTNO_LEN == 2); static JSBool -EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index, - JSCodeGenerator *cg) +EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index, CodeGenerator *cg) { JSOp bigSuffix; ptrdiff_t off; @@ -1974,32 +1950,36 @@ EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index, return JS_FALSE; /* Emit [op, slot, index]. */ - off = js_EmitN(cx, cg, op, 2 + INDEX_LEN); + off = EmitN(cx, cg, op, 2 + INDEX_LEN); if (off < 0) return JS_FALSE; pc = CG_CODE(cg, off); SET_UINT16(pc, slot); pc += 2; SET_INDEX(pc, index); - return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0; + return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0; } +} /* namespace frontend */ + bool -JSCodeGenerator::shouldNoteClosedName(JSParseNode *pn) +CodeGenerator::shouldNoteClosedName(ParseNode *pn) { return !callsEval() && pn->isDefn() && pn->isClosed(); } +namespace frontend { + /* * Adjust the slot for a block local to account for the number of variables * that share the same index space with locals. Due to the incremental code * generation for top-level script, we do the adjustment via code patching in - * Compiler::compileScript; see comments there. + * BytecodeCompiler::compileScript; see comments there. * * The function returns -1 on failures. */ static jsint -AdjustBlockSlot(JSContext *cx, JSCodeGenerator *cg, jsint slot) +AdjustBlockSlot(JSContext *cx, CodeGenerator *cg, jsint slot) { JS_ASSERT((jsuint) slot < cg->maxStackDepth); if (cg->inFunction()) { @@ -2013,7 +1993,7 @@ AdjustBlockSlot(JSContext *cx, JSCodeGenerator *cg, jsint slot) } static bool -EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg) +EmitEnterBlock(JSContext *cx, ParseNode *pn, CodeGenerator *cg) { JS_ASSERT(pn->isKind(TOK_LEXICALSCOPE)); if (!EmitObjectOp(cx, pn->pn_objbox, JSOP_ENTERBLOCK, cg)) @@ -2034,12 +2014,12 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg) continue; } - JSDefinition *dn = (JSDefinition *) v.toPrivate(); + Definition *dn = (Definition *) v.toPrivate(); JS_ASSERT(dn->isDefn()); JS_ASSERT(uintN(dn->frameSlot() + depth) < JS_BIT(16)); dn->pn_cookie.set(dn->pn_cookie.level(), uint16(dn->frameSlot() + depth)); #ifdef DEBUG - for (JSParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { + for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { JS_ASSERT(pnu->pn_lexdef == dn); JS_ASSERT(!(pnu->pn_dflags & PND_BOUND)); JS_ASSERT(pnu->pn_cookie.isFree()); @@ -2056,9 +2036,9 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg) } /* - * If clones of this block will have any extensible parents, then the clones - * must get unique shapes; see the comments for js::Bindings:: - * extensibleParents. + * If clones of this block will have any extensible parents, then the + * clones must get unique shapes; see the comments for + * js::Bindings::extensibleParents. */ if ((cg->flags & TCF_FUN_EXTENSIBLE_SCOPE) || cg->bindings.extensibleParents()) @@ -2068,8 +2048,7 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg) } static JSBool -EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, - JSObjectBox *box) +EmitLeaveBlock(JSContext *cx, CodeGenerator *cg, JSOp op, ObjectBox *box) { JSOp bigSuffix; uintN count = OBJ_BLOCK_COUNT(cx, box->object); @@ -2077,9 +2056,9 @@ EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, bigSuffix = EmitBigIndexPrefix(cx, cg, box->index); if (bigSuffix == JSOP_FALSE) return JS_FALSE; - if (js_Emit5(cx, cg, op, count, box->index) < 0) + if (Emit5(cx, cg, op, count, box->index) < 0) return JS_FALSE; - return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0; + return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0; } /* @@ -2104,7 +2083,7 @@ EmitLeaveBlock(JSContext *cx, JSCodeGenerator *cg, JSOp op, * foo(); */ static bool -TryConvertToGname(JSCodeGenerator *cg, JSParseNode *pn, JSOp *op) +TryConvertToGname(CodeGenerator *cg, ParseNode *pn, JSOp *op) { if (cg->compileAndGo() && cg->compiler()->globalScope->globalObj && @@ -2133,7 +2112,7 @@ TryConvertToGname(JSCodeGenerator *cg, JSParseNode *pn, JSOp *op) // that is |dn| or whose definition is |dn|. |pn->pn_cookie| is an outparam // that will be free (meaning no binding), or a slot number. static bool -BindKnownGlobal(JSContext *cx, JSCodeGenerator *cg, JSParseNode *dn, JSParseNode *pn, JSAtom *atom) +BindKnownGlobal(JSContext *cx, CodeGenerator *cg, ParseNode *dn, ParseNode *pn, JSAtom *atom) { // Cookie is an outparam; make sure caller knew to clear it. JS_ASSERT(pn->pn_cookie.isFree()); @@ -2151,7 +2130,7 @@ BindKnownGlobal(JSContext *cx, JSCodeGenerator *cg, JSParseNode *dn, JSParseNode JS_ASSERT(!!p); index = p.value(); } else { - JSCodeGenerator *globalcg = globalScope->cg; + CodeGenerator *globalcg = globalScope->cg; // If the definition is bound, and we're in the same cg, we can re-use // its cookie. @@ -2177,17 +2156,17 @@ BindKnownGlobal(JSContext *cx, JSCodeGenerator *cg, JSParseNode *dn, JSParseNode // See BindKnownGlobal()'s comment. static bool -BindGlobal(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSAtom *atom) +BindGlobal(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSAtom *atom) { pn->pn_cookie.makeFree(); - JSDefinition *dn; + Definition *dn; if (pn->isUsed()) { dn = pn->pn_lexdef; } else { if (!pn->isDefn()) return true; - dn = (JSDefinition *)pn; + dn = (Definition *)pn; } // Only optimize for defined globals. @@ -2212,15 +2191,15 @@ BindGlobal(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSAtom *atom) * * NB: if you add more opcodes specialized from JSOP_NAME, etc., don't forget * to update the TOK_FOR (for-in) and TOK_ASSIGN (op=, e.g. +=) special cases - * in js_EmitTree. + * in EmitTree. */ static JSBool -BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +BindNameToSlot(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { - JSDefinition *dn; + Definition *dn; JSOp op; JSAtom *atom; - JSDefinition::Kind dn_kind; + Definition::Kind dn_kind; JS_ASSERT(pn->isKind(TOK_NAME)); @@ -2245,7 +2224,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } else { if (!pn->isDefn()) return JS_TRUE; - dn = (JSDefinition *) pn; + dn = (Definition *) pn; } op = pn->getOp(); @@ -2271,7 +2250,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case JSOP_SETCONST: break; case JSOP_DELNAME: - if (dn_kind != JSDefinition::UNKNOWN) { + if (dn_kind != Definition::UNKNOWN) { if (cg->parser->callerFrame && dn->isTopLevel()) JS_ASSERT(cg->compileAndGo()); else @@ -2424,8 +2403,8 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } uintN slot = cookie.slot(); - if (slot != UpvarCookie::CALLEE_SLOT && dn_kind != JSDefinition::ARG) { - JSTreeContext *tc = cg; + if (slot != UpvarCookie::CALLEE_SLOT && dn_kind != Definition::ARG) { + TreeContext *tc = cg; do { tc = tc->parent; } while (tc->staticLevel != level); @@ -2450,10 +2429,10 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * rewrite pn_op and update pn accordingly. */ switch (dn_kind) { - case JSDefinition::UNKNOWN: + case Definition::UNKNOWN: return JS_TRUE; - case JSDefinition::LET: + case Definition::LET: switch (op) { case JSOP_NAME: op = JSOP_GETLOCAL; break; case JSOP_SETNAME: op = JSOP_SETLOCAL; break; @@ -2465,7 +2444,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } break; - case JSDefinition::ARG: + case Definition::ARG: switch (op) { case JSOP_NAME: op = JSOP_GETARG; break; case JSOP_SETNAME: op = JSOP_SETARG; break; @@ -2478,7 +2457,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(!pn->isConst()); break; - case JSDefinition::VAR: + case Definition::VAR: if (dn->isOp(JSOP_CALLEE)) { JS_ASSERT(op != JSOP_CALLEE); JS_ASSERT((cg->fun()->flags & JSFUN_LAMBDA) && atom == cg->fun()->atom); @@ -2520,9 +2499,9 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* FALL THROUGH */ default: - JS_ASSERT_IF(dn_kind != JSDefinition::FUNCTION, - dn_kind == JSDefinition::VAR || - dn_kind == JSDefinition::CONST); + JS_ASSERT_IF(dn_kind != Definition::FUNCTION, + dn_kind == Definition::VAR || + dn_kind == Definition::CONST); switch (op) { case JSOP_NAME: op = JSOP_GETLOCAL; break; case JSOP_SETNAME: op = JSOP_SETLOCAL; break; @@ -2533,7 +2512,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break; default: JS_NOT_REACHED("local"); } - JS_ASSERT_IF(dn_kind == JSDefinition::CONST, pn->pn_dflags & PND_CONST); + JS_ASSERT_IF(dn_kind == Definition::CONST, pn->pn_dflags & PND_CONST); break; } @@ -2544,8 +2523,10 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_TRUE; } +} /* namespace frontend */ + bool -JSCodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie) +CodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie) { if (!globalMap.ensureMap(context())) return false; @@ -2578,6 +2559,8 @@ JSCodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie) return globalMap->add(p, atom, globalUseIndex); } +namespace frontend { + /* * If pn contains a useful expression, return true with *answer set to true. * If pn contains a useless expression, return true with *answer set to false. @@ -2591,11 +2574,10 @@ JSCodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie) * pop bytecode. */ static JSBool -CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, - JSBool *answer) +CheckSideEffects(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSBool *answer) { JSBool ok; - JSParseNode *pn2; + ParseNode *pn2; ok = JS_TRUE; if (!pn || *answer) @@ -2786,8 +2768,7 @@ CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, } static JSBool -EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, - JSBool callContext) +EmitNameOp(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSBool callContext) { JSOp op; @@ -2819,9 +2800,9 @@ EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, } if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) { - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; - if (callContext && js_Emit1(cx, cg, JSOP_PUSH) < 0) + if (callContext && Emit1(cx, cg, JSOP_PUSH) < 0) return JS_FALSE; } else { if (!pn->pn_cookie.isFree()) { @@ -2836,42 +2817,37 @@ EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, } #if JS_HAS_XML_SUPPORT -static JSBool -EmitXMLName(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +static bool +EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { - JSParseNode *pn2; - uintN oldflags; - JS_ASSERT(pn->isKind(TOK_UNARYOP)); JS_ASSERT(pn->isOp(JSOP_XMLNAME)); JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME); - pn2 = pn->pn_kid; - oldflags = cg->flags; + ParseNode *pn2 = pn->pn_kid; + uintN oldflags = cg->flags; cg->flags &= ~TCF_IN_FOR_INIT; - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; + if (!EmitTree(cx, cg, pn2)) + return false; cg->flags |= oldflags & TCF_IN_FOR_INIT; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pn2->pn_offset) < 0) { - return JS_FALSE; - } + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - pn2->pn_offset) < 0) + return false; - return js_Emit1(cx, cg, op) >= 0; + return Emit1(cx, cg, op) >= 0; } #endif static inline bool -EmitElemOpBase(JSContext *cx, JSCodeGenerator *cg, JSOp op) +EmitElemOpBase(JSContext *cx, CodeGenerator *cg, JSOp op) { - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return false; CheckTypeSet(cx, cg, op); return true; } static bool -EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +EmitSpecialPropOp(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { /* * Special case for obj.__proto__ to deoptimize away from fast paths in the @@ -2886,11 +2862,11 @@ EmitSpecialPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) return EmitElemOpBase(cx, cg, op); } -static JSBool -EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, +static bool +EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg, JSBool callContext, JSOp *psuffix = NULL) { - JSParseNode *pn2, *pndot, *pnup, *pndown; + ParseNode *pn2, *pndot, *pnup, *pndown; ptrdiff_t top; JS_ASSERT(pn->isArity(PN_NAME)); @@ -2899,8 +2875,8 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, /* Special case deoptimization for __proto__. */ if ((op == JSOP_GETPROP || op == JSOP_CALLPROP) && pn->pn_atom == cx->runtime->atomState.protoAtom) { - if (pn2 && !js_EmitTree(cx, cg, pn2)) - return JS_FALSE; + if (pn2 && !EmitTree(cx, cg, pn2)) + return false; return EmitSpecialPropOp(cx, pn, callContext ? JSOP_CALLELEM : JSOP_GETELEM, cg); } @@ -2915,11 +2891,11 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, * inference is enabled this is optimized separately. */ if (!BindNameToSlot(cx, cg, pn2)) - return JS_FALSE; + return false; if (!cx->typeInferenceEnabled() && pn->pn_atom == cx->runtime->atomState.lengthAtom) { if (pn2->isOp(JSOP_ARGUMENTS)) - return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0; + return Emit1(cx, cg, JSOP_ARGCNT) >= 0; } } } @@ -2946,22 +2922,20 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, } /* pndown is a primary expression, not a dotted property reference. */ - if (!js_EmitTree(cx, cg, pndown)) - return JS_FALSE; + if (!EmitTree(cx, cg, pndown)) + return false; do { /* Walk back up the list, emitting annotated name ops. */ - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pndown->pn_offset) < 0) { - return JS_FALSE; - } + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - pndown->pn_offset) < 0) + return false; /* Special case deoptimization on __proto__, as above. */ if (pndot->isArity(PN_NAME) && pndot->pn_atom == cx->runtime->atomState.protoAtom) { if (!EmitSpecialPropOp(cx, pndot, JSOP_GETELEM, cg)) - return JS_FALSE; + return false; } else if (!EmitAtomOp(cx, pndot, pndot->getOp(), cg)) { - return JS_FALSE; + return false; } /* Reverse the pn_expr link again. */ @@ -2970,25 +2944,23 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg, pndown = pndot; } while ((pndot = pnup) != NULL); } else { - if (!js_EmitTree(cx, cg, pn2)) - return JS_FALSE; + if (!EmitTree(cx, cg, pn2)) + return false; } - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pn2->pn_offset) < 0) { - return JS_FALSE; - } + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - pn2->pn_offset) < 0) + return false; return EmitAtomOp(cx, pn, op, cg, psuffix); } static bool -EmitPropIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +EmitPropIncDec(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { JSOp suffix = JSOP_NOP; if (!EmitPropOp(cx, pn, op, cg, false, &suffix)) return false; - if (js_Emit1(cx, cg, JSOP_NOP) < 0) + if (Emit1(cx, cg, JSOP_NOP) < 0) return false; /* @@ -2997,7 +2969,7 @@ EmitPropIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) */ int start = CG_OFFSET(cg); - if (suffix != JSOP_NOP && js_Emit1(cx, cg, suffix) < 0) + if (suffix != JSOP_NOP && Emit1(cx, cg, suffix) < 0) return false; const JSCodeSpec *cs = &js_CodeSpec[op]; @@ -3008,46 +2980,46 @@ EmitPropIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) JSOp binop = (cs->format & JOF_INC) ? JSOP_ADD : JSOP_SUB; // OBJ - if (js_Emit1(cx, cg, JSOP_DUP) < 0) // OBJ OBJ + if (Emit1(cx, cg, JSOP_DUP) < 0) // OBJ OBJ return false; if (!EmitAtomOp(cx, pn, JSOP_GETPROP, cg)) // OBJ V return false; - if (js_Emit1(cx, cg, JSOP_POS) < 0) // OBJ N + if (Emit1(cx, cg, JSOP_POS) < 0) // OBJ N return false; - if (post && js_Emit1(cx, cg, JSOP_DUP) < 0) // OBJ N? N + if (post && Emit1(cx, cg, JSOP_DUP) < 0) // OBJ N? N return false; - if (js_Emit1(cx, cg, JSOP_ONE) < 0) // OBJ N? N 1 + if (Emit1(cx, cg, JSOP_ONE) < 0) // OBJ N? N 1 return false; - if (js_Emit1(cx, cg, binop) < 0) // OBJ N? N+1 + if (Emit1(cx, cg, binop) < 0) // OBJ N? N+1 return false; if (post) { - if (js_Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N? N+1 OBJ + if (Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N? N+1 OBJ return false; - if (js_Emit1(cx, cg, JSOP_SWAP) < 0) // N? OBJ N+1 + if (Emit1(cx, cg, JSOP_SWAP) < 0) // N? OBJ N+1 return false; } if (!EmitAtomOp(cx, pn, JSOP_SETPROP, cg)) // N? N+1 return false; - if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT + if (post && Emit1(cx, cg, JSOP_POP) < 0) // RESULT return false; UpdateDecomposeLength(cg, start); - if (suffix != JSOP_NOP && js_Emit1(cx, cg, suffix) < 0) + if (suffix != JSOP_NOP && Emit1(cx, cg, suffix) < 0) return false; return true; } static bool -EmitNameIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +EmitNameIncDec(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { JSOp suffix = JSOP_NOP; if (!EmitAtomOp(cx, pn, op, cg, &suffix)) return false; - if (js_Emit1(cx, cg, JSOP_NOP) < 0) + if (Emit1(cx, cg, JSOP_NOP) < 0) return false; /* Remove the result to restore the stack depth before the INCNAME. */ @@ -3055,7 +3027,7 @@ EmitNameIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) int start = CG_OFFSET(cg); - if (suffix != JSOP_NOP && js_Emit1(cx, cg, suffix) < 0) + if (suffix != JSOP_NOP && Emit1(cx, cg, suffix) < 0) return false; const JSCodeSpec *cs = &js_CodeSpec[op]; @@ -3070,40 +3042,40 @@ EmitNameIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) return false; if (!EmitAtomOp(cx, pn, global ? JSOP_GETGNAME : JSOP_NAME, cg)) // OBJ V return false; - if (js_Emit1(cx, cg, JSOP_POS) < 0) // OBJ N + if (Emit1(cx, cg, JSOP_POS) < 0) // OBJ N return false; - if (post && js_Emit1(cx, cg, JSOP_DUP) < 0) // OBJ N? N + if (post && Emit1(cx, cg, JSOP_DUP) < 0) // OBJ N? N return false; - if (js_Emit1(cx, cg, JSOP_ONE) < 0) // OBJ N? N 1 + if (Emit1(cx, cg, JSOP_ONE) < 0) // OBJ N? N 1 return false; - if (js_Emit1(cx, cg, binop) < 0) // OBJ N? N+1 + if (Emit1(cx, cg, binop) < 0) // OBJ N? N+1 return false; if (post) { - if (js_Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N? N+1 OBJ + if (Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N? N+1 OBJ return false; - if (js_Emit1(cx, cg, JSOP_SWAP) < 0) // N? OBJ N+1 + if (Emit1(cx, cg, JSOP_SWAP) < 0) // N? OBJ N+1 return false; } if (!EmitAtomOp(cx, pn, global ? JSOP_SETGNAME : JSOP_SETNAME, cg)) // N? N+1 return false; - if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT + if (post && Emit1(cx, cg, JSOP_POP) < 0) // RESULT return false; UpdateDecomposeLength(cg, start); - if (suffix != JSOP_NOP && js_Emit1(cx, cg, suffix) < 0) + if (suffix != JSOP_NOP && Emit1(cx, cg, suffix) < 0) return false; return true; } static JSBool -EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { ptrdiff_t top; - JSParseNode *left, *right, *next, ltmp, rtmp; + ParseNode *left, *right, *next; int32_t slot; top = CG_OFFSET(cg); @@ -3123,7 +3095,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) */ if (left->isKind(TOK_NAME) && next->isKind(TOK_NUMBER)) { if (!BindNameToSlot(cx, cg, left)) - return JS_FALSE; + return false; if (left->isOp(JSOP_ARGUMENTS) && JSDOUBLE_IS_INT32(next->pn_dval, &slot) && jsuint(slot) < JS_BIT(16) && @@ -3151,40 +3123,42 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) */ JS_ASSERT(next != right || pn->pn_count == 3); if (left == pn->pn_head) { - if (!js_EmitTree(cx, cg, left)) - return JS_FALSE; + if (!EmitTree(cx, cg, left)) + return false; } while (next != right) { - if (!js_EmitTree(cx, cg, next)) - return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) - return JS_FALSE; + if (!EmitTree(cx, cg, next)) + return false; + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) + return false; if (!EmitElemOpBase(cx, cg, JSOP_GETELEM)) - return JS_FALSE; + return false; next = next->pn_next; } } else { if (pn->isArity(PN_NAME)) { /* * Set left and right so pn appears to be a TOK_LB node, instead - * of a TOK_DOT node. See the TOK_FOR/IN case in js_EmitTree, and + * of a TOK_DOT node. See the TOK_FOR/IN case in EmitTree, and * EmitDestructuringOps nearer below. In the destructuring case, * the base expression (pn_expr) of the name may be null, which * means we have to emit a JSOP_BINDNAME. */ left = pn->maybeExpr(); if (!left) { - left = <mp; + left = NullaryNode::create(cg); + if (!left) + return false; left->setKind(TOK_STRING); left->setOp(JSOP_BINDNAME); - left->setArity(PN_NULLARY); left->pn_pos = pn->pn_pos; left->pn_atom = pn->pn_atom; } - right = &rtmp; + right = NullaryNode::create(cg); + if (!right) + return false; right->setKind(TOK_STRING); - right->setOp(js_IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING); - right->setArity(PN_NULLARY); + right->setOp(IsIdentifier(pn->pn_atom) ? JSOP_QNAMEPART : JSOP_STRING); right->pn_pos = pn->pn_pos; right->pn_atom = pn->pn_atom; } else { @@ -3201,7 +3175,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) left->isKind(TOK_NAME) && right->isKind(TOK_NUMBER)) { if (!BindNameToSlot(cx, cg, left)) - return JS_FALSE; + return false; if (left->isOp(JSOP_ARGUMENTS) && JSDOUBLE_IS_INT32(right->pn_dval, &slot) && jsuint(slot) < JS_BIT(16) && @@ -3210,26 +3184,26 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) (!cg->mutatesParameter() && !cg->callsEval()))) { left->pn_offset = right->pn_offset = top; EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot); - return JS_TRUE; + return true; } } - if (!js_EmitTree(cx, cg, left)) - return JS_FALSE; + if (!EmitTree(cx, cg, left)) + return false; } /* The right side of the descendant operator is implicitly quoted. */ JS_ASSERT(op != JSOP_DESCENDANTS || !right->isKind(TOK_STRING) || right->isOp(JSOP_QNAMEPART)); - if (!js_EmitTree(cx, cg, right)) - return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) - return JS_FALSE; + if (!EmitTree(cx, cg, right)) + return false; + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) + return false; return EmitElemOpBase(cx, cg, op); } static bool -EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) +EmitElemIncDec(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg) { if (pn) { if (!EmitElemOp(cx, pn, op, cg)) @@ -3238,7 +3212,7 @@ EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) if (!EmitElemOpBase(cx, cg, op)) return false; } - if (js_Emit1(cx, cg, JSOP_NOP) < 0) + if (Emit1(cx, cg, JSOP_NOP) < 0) return false; /* INCELEM pops two values and pushes one, so restore the initial depth. */ @@ -3258,33 +3232,33 @@ EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) * it inside both the GETELEM and the SETELEM. */ // OBJ KEY* - if (js_Emit1(cx, cg, JSOP_TOID) < 0) // OBJ KEY + if (Emit1(cx, cg, JSOP_TOID) < 0) // OBJ KEY return false; - if (js_Emit1(cx, cg, JSOP_DUP2) < 0) // OBJ KEY OBJ KEY + if (Emit1(cx, cg, JSOP_DUP2) < 0) // OBJ KEY OBJ KEY return false; if (!EmitElemOpBase(cx, cg, JSOP_GETELEM)) // OBJ KEY V return false; - if (js_Emit1(cx, cg, JSOP_POS) < 0) // OBJ KEY N + if (Emit1(cx, cg, JSOP_POS) < 0) // OBJ KEY N return false; - if (post && js_Emit1(cx, cg, JSOP_DUP) < 0) // OBJ KEY N? N + if (post && Emit1(cx, cg, JSOP_DUP) < 0) // OBJ KEY N? N return false; - if (js_Emit1(cx, cg, JSOP_ONE) < 0) // OBJ KEY N? N 1 + if (Emit1(cx, cg, JSOP_ONE) < 0) // OBJ KEY N? N 1 return false; - if (js_Emit1(cx, cg, binop) < 0) // OBJ KEY N? N+1 + if (Emit1(cx, cg, binop) < 0) // OBJ KEY N? N+1 return false; if (post) { - if (js_Emit2(cx, cg, JSOP_PICK, (jsbytecode)3) < 0) // KEY N N+1 OBJ + if (Emit2(cx, cg, JSOP_PICK, (jsbytecode)3) < 0) // KEY N N+1 OBJ return false; - if (js_Emit2(cx, cg, JSOP_PICK, (jsbytecode)3) < 0) // N N+1 OBJ KEY + if (Emit2(cx, cg, JSOP_PICK, (jsbytecode)3) < 0) // N N+1 OBJ KEY return false; - if (js_Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N OBJ KEY N+1 + if (Emit2(cx, cg, JSOP_PICK, (jsbytecode)2) < 0) // N OBJ KEY N+1 return false; } if (!EmitElemOpBase(cx, cg, JSOP_SETELEM)) // N? N+1 return false; - if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT + if (post && Emit1(cx, cg, JSOP_POP) < 0) // RESULT return false; UpdateDecomposeLength(cg, start); @@ -3293,7 +3267,7 @@ EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) } static JSBool -EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) +EmitNumberOp(JSContext *cx, jsdouble dval, CodeGenerator *cg) { int32_t ival; uint32 u; @@ -3302,23 +3276,23 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) if (JSDOUBLE_IS_INT32(dval, &ival)) { if (ival == 0) - return js_Emit1(cx, cg, JSOP_ZERO) >= 0; + return Emit1(cx, cg, JSOP_ZERO) >= 0; if (ival == 1) - return js_Emit1(cx, cg, JSOP_ONE) >= 0; + return Emit1(cx, cg, JSOP_ONE) >= 0; if ((jsint)(int8)ival == ival) - return js_Emit2(cx, cg, JSOP_INT8, (jsbytecode)(int8)ival) >= 0; + return Emit2(cx, cg, JSOP_INT8, (jsbytecode)(int8)ival) >= 0; u = (uint32)ival; if (u < JS_BIT(16)) { EMIT_UINT16_IMM_OP(JSOP_UINT16, u); } else if (u < JS_BIT(24)) { - off = js_EmitN(cx, cg, JSOP_UINT24, 3); + off = EmitN(cx, cg, JSOP_UINT24, 3); if (off < 0) return JS_FALSE; pc = CG_CODE(cg, off); SET_UINT24(pc, u); } else { - off = js_EmitN(cx, cg, JSOP_INT32, 4); + off = EmitN(cx, cg, JSOP_INT32, 4); if (off < 0) return JS_FALSE; pc = CG_CODE(cg, off); @@ -3355,28 +3329,28 @@ AllocateSwitchConstant(JSContext *cx) * though EXPR is evaluated in the enclosing scope; it does not see x. * * In those cases we use TempPopScope around the code to emit EXPR. It - * temporarily removes the let-scope from the JSCodeGenerator's scope stack and + * temporarily removes the let-scope from the CodeGenerator's scope stack and * emits extra bytecode to ensure that js::GetBlockChain also finds the correct * scope at run time. */ class TempPopScope { - JSStmtInfo *savedStmt; - JSStmtInfo *savedScopeStmt; - JSObjectBox *savedBlockBox; + StmtInfo *savedStmt; + StmtInfo *savedScopeStmt; + ObjectBox *savedBlockBox; public: TempPopScope() : savedStmt(NULL), savedScopeStmt(NULL), savedBlockBox(NULL) {} - bool popBlock(JSContext *cx, JSCodeGenerator *cg) { + bool popBlock(JSContext *cx, CodeGenerator *cg) { savedStmt = cg->topStmt; savedScopeStmt = cg->topScopeStmt; savedBlockBox = cg->blockChainBox; if (cg->topStmt->type == STMT_FOR_LOOP || cg->topStmt->type == STMT_FOR_IN_LOOP) - js_PopStatement(cg); + PopStatementTC(cg); JS_ASSERT(STMT_LINKS_SCOPE(cg->topStmt)); JS_ASSERT(cg->topStmt->flags & SIF_SCOPE); - js_PopStatement(cg); + PopStatementTC(cg); /* * Since we have changed the block chain, emit an instruction marking @@ -3385,35 +3359,35 @@ class TempPopScope { * * FIXME bug 671360 - The JSOP_NOP instruction should not be necessary. */ - return js_Emit1(cx, cg, JSOP_NOP) >= 0 && EmitBlockChain(cx, cg); + return Emit1(cx, cg, JSOP_NOP) >= 0 && EmitBlockChain(cx, cg); } - bool repushBlock(JSContext *cx, JSCodeGenerator *cg) { + bool repushBlock(JSContext *cx, CodeGenerator *cg) { JS_ASSERT(savedStmt); cg->topStmt = savedStmt; cg->topScopeStmt = savedScopeStmt; cg->blockChainBox = savedBlockBox; - return js_Emit1(cx, cg, JSOP_NOP) >= 0 && EmitBlockChain(cx, cg); + return Emit1(cx, cg, JSOP_NOP) >= 0 && EmitBlockChain(cx, cg); } }; static JSBool -EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitSwitch(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { JSOp switchOp; JSBool ok, hasDefault, constPropagated; ptrdiff_t top, off, defaultOffset; - JSParseNode *pn2, *pn3, *pn4; + ParseNode *pn2, *pn3, *pn4; uint32 caseCount, tableLength; - JSParseNode **table; + ParseNode **table; int32_t i, low, high; intN noteIndex; size_t switchSize, tableSize; jsbytecode *pc, *savepc; #if JS_HAS_BLOCK_SCOPE - JSObjectBox *box; + ObjectBox *box; #endif - JSStmtInfo stmtInfo; + StmtInfo stmtInfo; /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */ switchOp = JSOP_TABLESWITCH; @@ -3438,7 +3412,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * find the discriminant on top of stack. */ box = pn2->pn_objbox; - js_PushBlockScope(cg, &stmtInfo, box, -1); + PushBlockScope(cg, &stmtInfo, box, -1); stmtInfo.type = STMT_SWITCH; /* Emit JSOP_ENTERBLOCK before code to evaluate the discriminant. */ @@ -3463,16 +3437,16 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Emit code for the discriminant first (or nearly first, in the case of a * switch whose body is a block scope). */ - if (!js_EmitTree(cx, cg, pn->pn_left)) + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; /* Switch bytecodes run from here till end of final case. */ top = CG_OFFSET(cg); #if !JS_HAS_BLOCK_SCOPE - js_PushStatement(cg, &stmtInfo, STMT_SWITCH, top); + PushStatement(cg, &stmtInfo, STMT_SWITCH, top); #else if (pn2->isKind(TOK_LC)) { - js_PushStatement(cg, &stmtInfo, STMT_SWITCH, top); + PushStatement(cg, &stmtInfo, STMT_SWITCH, top); } else { /* Re-push the switch's statement info record. */ if (!tps.repushBlock(cx, cg)) @@ -3656,7 +3630,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Emit a note with two offsets: first tells total switch code length, * second tells offset to first JSOP_CASE if condswitch. */ - noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0); + noteIndex = NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0); if (noteIndex < 0) return JS_FALSE; @@ -3686,12 +3660,12 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * If switchOp is JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH, it is crucial * to emit the immediate operand(s) by which bytecode readers such as * BuildSpanDepTable discover the length of the switch opcode *before* - * calling js_SetJumpOffset (which may call BuildSpanDepTable). It's + * calling SetJumpOffset (which may call BuildSpanDepTable). It's * also important to zero all unknown jump offset immediate operands, * so they can be converted to span dependencies with null targets to - * be computed later (js_EmitN zeros switchSize bytes after switchOp). + * be computed later (EmitN zeros switchSize bytes after switchOp). */ - if (js_EmitN(cx, cg, switchOp, switchSize) < 0) + if (EmitN(cx, cg, switchOp, switchSize) < 0) return JS_FALSE; off = -1; @@ -3702,20 +3676,18 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Emit code for evaluating cases and jumping to case statements. */ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { pn4 = pn3->pn_left; - if (pn4 && !js_EmitTree(cx, cg, pn4)) + if (pn4 && !EmitTree(cx, cg, pn4)) return JS_FALSE; if (caseNoteIndex >= 0) { /* off is the previous JSOP_CASE's bytecode offset. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, - CG_OFFSET(cg) - off)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, CG_OFFSET(cg) - off)) return JS_FALSE; - } } if (!pn4) { JS_ASSERT(pn3->isKind(TOK_DEFAULT)); continue; } - caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); + caseNoteIndex = NewSrcNote2(cx, cg, SRC_PCDELTA, 0); if (caseNoteIndex < 0) return JS_FALSE; off = EmitJump(cx, cg, JSOP_CASE, 0); @@ -3727,9 +3699,8 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Switch note's second offset is to first JSOP_CASE. */ noteCount = CG_NOTE_COUNT(cg); - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, off - top)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, off - top)) return JS_FALSE; - } noteCountDelta = CG_NOTE_COUNT(cg) - noteCount; if (noteCountDelta != 0) caseNoteIndex += noteCountDelta; @@ -3739,14 +3710,14 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * If we didn't have an explicit default (which could fall in between - * cases, preventing us from fusing this js_SetSrcNoteOffset with the - * call in the loop above), link the last case to the implicit default - * for the decompiler. + * cases, preventing us from fusing this SetSrcNoteOffset with the call + * in the loop above), link the last case to the implicit default for + * the decompiler. */ if (!hasDefault && caseNoteIndex >= 0 && - !js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, - CG_OFFSET(cg) - off)) { + !SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0, CG_OFFSET(cg) - off)) + { return JS_FALSE; } @@ -3771,7 +3742,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) */ if (tableLength != 0) { tableSize = (size_t)tableLength * sizeof *table; - table = (JSParseNode **) cx->malloc_(tableSize); + table = (ParseNode **) cx->malloc_(tableSize); if (!table) return JS_FALSE; memset(table, 0, tableSize); @@ -3802,8 +3773,8 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * We have already generated at least one big jump so we must * explicitly add span dependencies for the switch jumps. When - * called below, js_SetJumpOffset can only do it when patching - * the first big jump or when cg->spanDeps is null. + * called below, SetJumpOffset can only do it when patching the + * first big jump or when cg->spanDeps is null. */ if (!AddSwitchSpanDeps(cx, cg, CG_CODE(cg, top))) goto bad; @@ -3829,7 +3800,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!cg->makeAtomIndex(pn4->pn_atom, &index)) goto bad; CG_NEXT(cg) = pc; - if (js_NewSrcNote2(cx, cg, SRC_LABEL, ptrdiff_t(index)) < 0) + if (NewSrcNote2(cx, cg, SRC_LABEL, ptrdiff_t(index)) < 0) goto bad; } pc += JUMP_OFFSET_LEN; @@ -3844,7 +3815,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!cg->makeAtomIndex(pn4->pn_atom, &index)) goto bad; CG_NEXT(cg) = pc; - if (js_NewSrcNote2(cx, cg, SRC_LABEL, ptrdiff_t(index)) < 0) + if (NewSrcNote2(cx, cg, SRC_LABEL, ptrdiff_t(index)) < 0) goto bad; } pc += INDEX_LEN + JUMP_OFFSET_LEN; @@ -3859,7 +3830,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (switchOp == JSOP_CONDSWITCH && !pn3->isKind(TOK_DEFAULT)) CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, pn3->pn_offset, goto bad); pn4 = pn3->pn_right; - ok = js_EmitTree(cx, cg, pn4); + ok = EmitTree(cx, cg, pn4); if (!ok) goto out; pn3->pn_offset = pn4->pn_offset; @@ -3879,13 +3850,12 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (switchOp == JSOP_CONDSWITCH) { pc = NULL; JS_ASSERT(defaultOffset != -1); - ok = js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset), - off - (defaultOffset - top)); + ok = SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset), off - (defaultOffset - top)); if (!ok) goto out; } else { pc = CG_CODE(cg, top); - ok = js_SetJumpOffset(cx, cg, pc, off); + ok = SetJumpOffset(cx, cg, pc, off); if (!ok) goto out; pc += JUMP_OFFSET_LEN; @@ -3893,7 +3863,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Set the SRC_SWITCH note's offset operand to tell end of switch. */ off = CG_OFFSET(cg) - top; - ok = js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off); + ok = SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off); if (!ok) goto out; @@ -3905,7 +3875,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) for (i = 0; i < (jsint)tableLength; i++) { pn3 = table[i]; off = pn3 ? pn3->pn_offset - top : 0; - ok = js_SetJumpOffset(cx, cg, pc, off); + ok = SetJumpOffset(cx, cg, pc, off); if (!ok) goto out; pc += JUMP_OFFSET_LEN; @@ -3923,7 +3893,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) pc += INDEX_LEN; off = pn3->pn_offset - top; - ok = js_SetJumpOffset(cx, cg, pc, off); + ok = SetJumpOffset(cx, cg, pc, off); if (!ok) goto out; pc += JUMP_OFFSET_LEN; @@ -3934,7 +3904,7 @@ out: if (table) cx->free_(table); if (ok) { - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); #if JS_HAS_BLOCK_SCOPE if (ok && pn->pn_right->isKind(TOK_LEXICALSCOPE)) @@ -3949,7 +3919,7 @@ bad: } JSBool -js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body) +EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body) { /* * The decompiler has assumptions about what may occur immediately after @@ -3962,7 +3932,7 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body) /* JSOP_GENERATOR must be the first instruction. */ CG_SWITCH_TO_PROLOG(cg); JS_ASSERT(CG_NEXT(cg) == CG_BASE(cg)); - if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0) + if (Emit1(cx, cg, JSOP_GENERATOR) < 0) return false; CG_SWITCH_TO_MAIN(cg); } @@ -3976,26 +3946,26 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body) */ if (cg->needsEagerArguments()) { CG_SWITCH_TO_PROLOG(cg); - if (js_Emit1(cx, cg, JSOP_ARGUMENTS) < 0 || js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_ARGUMENTS) < 0 || Emit1(cx, cg, JSOP_POP) < 0) return false; CG_SWITCH_TO_MAIN(cg); } if (cg->flags & TCF_FUN_UNBRAND_THIS) { CG_SWITCH_TO_PROLOG(cg); - if (js_Emit1(cx, cg, JSOP_UNBRANDTHIS) < 0) + if (Emit1(cx, cg, JSOP_UNBRANDTHIS) < 0) return false; CG_SWITCH_TO_MAIN(cg); } - return js_EmitTree(cx, cg, body) && - js_Emit1(cx, cg, JSOP_STOP) >= 0 && + return EmitTree(cx, cg, body) && + Emit1(cx, cg, JSOP_STOP) >= 0 && JSScript::NewScriptFromCG(cx, cg); } static bool -MaybeEmitVarDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn, jsatomid *result) +MaybeEmitVarDecl(JSContext *cx, CodeGenerator *cg, JSOp prologOp, + ParseNode *pn, jsatomid *result) { jsatomid atomIndex; @@ -4034,12 +4004,10 @@ MaybeEmitVarDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, #if JS_HAS_DESTRUCTURING typedef JSBool -(*DestructuringDeclEmitter)(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn); +(*DestructuringDeclEmitter)(JSContext *cx, CodeGenerator *cg, JSOp prologOp, ParseNode *pn); static JSBool -EmitDestructuringDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn) +EmitDestructuringDecl(JSContext *cx, CodeGenerator *cg, JSOp prologOp, ParseNode *pn) { JS_ASSERT(pn->isKind(TOK_NAME)); if (!BindNameToSlot(cx, cg, pn)) @@ -4050,10 +4018,9 @@ EmitDestructuringDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, } static JSBool -EmitDestructuringDecls(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn) +EmitDestructuringDecls(JSContext *cx, CodeGenerator *cg, JSOp prologOp, ParseNode *pn) { - JSParseNode *pn2, *pn3; + ParseNode *pn2, *pn3; DestructuringDeclEmitter emitter; if (pn->isKind(TOK_RB)) { @@ -4079,10 +4046,10 @@ EmitDestructuringDecls(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, } static JSBool -EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn); +EmitDestructuringOpsHelper(JSContext *cx, CodeGenerator *cg, ParseNode *pn); static JSBool -EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitDestructuringLHS(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { /* * Now emit the lvalue opcode sequence. If the lvalue is a nested @@ -4093,14 +4060,14 @@ EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (pn->isKind(TOK_RB) || pn->isKind(TOK_RC)) { if (!EmitDestructuringOpsHelper(cx, cg, pn)) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; } else { if (pn->isKind(TOK_NAME)) { if (!BindNameToSlot(cx, cg, pn)) return JS_FALSE; if (pn->isConst() && !pn->isInitialized()) - return js_Emit1(cx, cg, JSOP_POP) >= 0; + return Emit1(cx, cg, JSOP_POP) >= 0; } switch (pn->getOp()) { @@ -4131,7 +4098,7 @@ EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) { jsuint slot = pn->pn_cookie.asInteger(); EMIT_UINT16_IMM_OP(pn->getOp(), slot); - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; break; } @@ -4141,9 +4108,9 @@ EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) ptrdiff_t top; top = CG_OFFSET(cg); - if (!js_EmitTree(cx, cg, pn)) + if (!EmitTree(cx, cg, pn)) return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) return JS_FALSE; if (!EmitElemOpBase(cx, cg, JSOP_ENUMELEM)) return JS_FALSE; @@ -4166,10 +4133,10 @@ EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * them in the lvalues identified by the matched property names. */ static JSBool -EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitDestructuringOpsHelper(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { jsuint index; - JSParseNode *pn2, *pn3; + ParseNode *pn2, *pn3; JSBool doElemOp; #ifdef DEBUG @@ -4181,8 +4148,8 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (pn->pn_count == 0) { /* Emit a DUP;POP sequence for the decompiler. */ - return js_Emit1(cx, cg, JSOP_DUP) >= 0 && - js_Emit1(cx, cg, JSOP_POP) >= 0; + return Emit1(cx, cg, JSOP_DUP) >= 0 && + Emit1(cx, cg, JSOP_POP) >= 0; } index = 0; @@ -4191,9 +4158,9 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Duplicate the value being destructured to use as a reference base. * If dup is not the first one, annotate it for the decompiler. */ - if (pn2 != pn->pn_head && js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0) + if (pn2 != pn->pn_head && NewSrcNote(cx, cg, SRC_CONTINUE) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_DUP) < 0) + if (Emit1(cx, cg, JSOP_DUP) < 0) return JS_FALSE; /* @@ -4217,7 +4184,7 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * annotate the index op with SRC_INITPROP so we know we are * not decompiling an array initialiser. */ - if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0) + if (NewSrcNote(cx, cg, SRC_INITPROP) < 0) return JS_FALSE; if (!EmitNumberOp(cx, pn3->pn_dval, cg)) return JS_FALSE; @@ -4245,7 +4212,7 @@ EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (pn3->isKind(TOK_COMMA) && pn3->isArity(PN_NULLARY)) { JS_ASSERT(pn->isKind(TOK_RB)); JS_ASSERT(pn2 == pn3); - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; } else { if (!EmitDestructuringLHS(cx, cg, pn3)) @@ -4275,8 +4242,7 @@ OpToDeclType(JSOp op) } static JSBool -EmitDestructuringOps(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn) +EmitDestructuringOps(JSContext *cx, CodeGenerator *cg, JSOp prologOp, ParseNode *pn) { /* * If we're called from a variable declaration, help the decompiler by @@ -4284,7 +4250,7 @@ EmitDestructuringOps(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, * If the destructuring initialiser is empty, our helper will emit a * JSOP_DUP followed by a JSOP_POP for the decompiler. */ - if (js_NewSrcNote2(cx, cg, SRC_DESTRUCT, OpToDeclType(prologOp)) < 0) + if (NewSrcNote2(cx, cg, SRC_DESTRUCT, OpToDeclType(prologOp)) < 0) return JS_FALSE; /* @@ -4295,11 +4261,11 @@ EmitDestructuringOps(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, } static JSBool -EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *lhs, JSParseNode *rhs) +EmitGroupAssignment(JSContext *cx, CodeGenerator *cg, JSOp prologOp, + ParseNode *lhs, ParseNode *rhs) { jsuint depth, limit, i, nslots; - JSParseNode *pn; + ParseNode *pn; depth = limit = (uintN) cg->stackDepth; for (pn = rhs->pn_head; pn; pn = pn->pn_next) { @@ -4310,12 +4276,12 @@ EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, /* MaybeEmitGroupAssignment won't call us if rhs is holey. */ JS_ASSERT(!(pn->isKind(TOK_COMMA) && pn->isArity(PN_NULLARY))); - if (!js_EmitTree(cx, cg, pn)) + if (!EmitTree(cx, cg, pn)) return JS_FALSE; ++limit; } - if (js_NewSrcNote2(cx, cg, SRC_GROUPASSIGN, OpToDeclType(prologOp)) < 0) + if (NewSrcNote2(cx, cg, SRC_GROUPASSIGN, OpToDeclType(prologOp)) < 0) return JS_FALSE; i = depth; @@ -4328,7 +4294,7 @@ EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, EMIT_UINT16_IMM_OP(JSOP_GETLOCAL, slot); if (pn->isKind(TOK_COMMA) && pn->isArity(PN_NULLARY)) { - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; } else { if (!EmitDestructuringLHS(cx, cg, pn)) @@ -4348,10 +4314,9 @@ EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, * we set *pop to JSOP_NOP so callers can veto emitting pn followed by a pop. */ static JSBool -MaybeEmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, - JSParseNode *pn, JSOp *pop) +MaybeEmitGroupAssignment(JSContext *cx, CodeGenerator *cg, JSOp prologOp, ParseNode *pn, JSOp *pop) { - JSParseNode *lhs, *rhs; + ParseNode *lhs, *rhs; JS_ASSERT(pn->isKind(TOK_ASSIGN)); JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV); @@ -4370,12 +4335,12 @@ MaybeEmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp, #endif /* JS_HAS_DESTRUCTURING */ static JSBool -EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, - JSBool inLetHead, ptrdiff_t *headNoteIndex) +EmitVariables(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSBool inLetHead, + ptrdiff_t *headNoteIndex) { bool forInVar, first; ptrdiff_t off, noteIndex, tmp; - JSParseNode *pn2, *pn3, *next; + ParseNode *pn2, *pn3, *next; JSOp op; jsatomid atomIndex; uintN oldflags; @@ -4407,12 +4372,12 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, #if JS_HAS_DESTRUCTURING if (pn2->isKind(TOK_RB) || pn2->isKind(TOK_RC)) { /* - * Emit variable binding ops, but not destructuring ops. - * The parser (see Variables, jsparse.c) has ensured that - * our caller will be the TOK_FOR/TOK_IN case in js_EmitTree, - * and that case will emit the destructuring code only after - * emitting an enumerating opcode and a branch that tests - * whether the enumeration ended. + * Emit variable binding ops, but not destructuring ops. The + * parser (see Parser::variables) has ensured that our caller + * will be the TOK_FOR/TOK_IN case in EmitTree, and that case + * will emit the destructuring code only after emitting an + * enumerating opcode and a branch that tests whether the + * enumeration ended. */ JS_ASSERT(forInVar); JS_ASSERT(pn->pn_count == 1); @@ -4472,7 +4437,7 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, if (!EmitDestructuringDecls(cx, cg, pn->getOp(), pn3)) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn2->pn_right)) + if (!EmitTree(cx, cg, pn2->pn_right)) return JS_FALSE; /* @@ -4525,13 +4490,14 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, EMIT_INDEX_OP(JSOP_BINDGNAME, atomIndex); } if (pn->isOp(JSOP_DEFCONST) && - !js_DefineCompileTimeConstant(cx, cg, pn2->pn_atom, pn3)) { + !DefineCompileTimeConstant(cx, cg, pn2->pn_atom, pn3)) + { return JS_FALSE; } oldflags = cg->flags; cg->flags &= ~TCF_IN_FOR_INIT; - if (!js_EmitTree(cx, cg, pn3)) + if (!EmitTree(cx, cg, pn3)) return JS_FALSE; cg->flags |= oldflags & TCF_IN_FOR_INIT; } @@ -4543,7 +4509,7 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, * a TOK_SEQ node to make the two statements appear as one. Therefore * if this declaration is part of a for-in loop head, we do not need to * emit op or any source note. Our caller, the TOK_FOR/TOK_IN case in - * js_EmitTree, will annotate appropriately. + * EmitTree, will annotate appropriately. */ JS_ASSERT_IF(pn2->isDefn(), pn3 == pn2->pn_expr); if (forInVar) { @@ -4554,16 +4520,17 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, if (first && !inLetHead && - js_NewSrcNote2(cx, cg, SRC_DECL, - (pn->isOp(JSOP_DEFCONST)) - ? SRC_DECL_CONST - : (pn->isOp(JSOP_DEFVAR)) - ? SRC_DECL_VAR - : SRC_DECL_LET) < 0) { + NewSrcNote2(cx, cg, SRC_DECL, + (pn->isOp(JSOP_DEFCONST)) + ? SRC_DECL_CONST + : (pn->isOp(JSOP_DEFVAR)) + ? SRC_DECL_VAR + : SRC_DECL_LET) < 0) + { return JS_FALSE; } if (op == JSOP_ARGUMENTS) { - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } else if (!pn2->pn_cookie.isFree()) { EMIT_UINT16_IMM_OP(op, atomIndex); @@ -4576,31 +4543,31 @@ EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, #endif tmp = CG_OFFSET(cg); if (noteIndex >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) return JS_FALSE; } if (!next) break; off = tmp; - noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); - if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0) + noteIndex = NewSrcNote2(cx, cg, SRC_PCDELTA, 0); + if (noteIndex < 0 || Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; } /* If this is a let head, emit and return a srcnote on the pop. */ if (inLetHead) { - *headNoteIndex = js_NewSrcNote(cx, cg, SRC_DECL); + *headNoteIndex = NewSrcNote(cx, cg, SRC_DECL); if (*headNoteIndex < 0) return JS_FALSE; if (!(pn->pn_xflags & PNX_POPVAR)) - return js_Emit1(cx, cg, JSOP_NOP) >= 0; + return Emit1(cx, cg, JSOP_NOP) >= 0; } - return !(pn->pn_xflags & PNX_POPVAR) || js_Emit1(cx, cg, JSOP_POP) >= 0; + return !(pn->pn_xflags & PNX_POPVAR) || Emit1(cx, cg, JSOP_POP) >= 0; } static bool -EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JSParseNode *rhs) +EmitAssignment(JSContext *cx, CodeGenerator *cg, ParseNode *lhs, JSOp op, ParseNode *rhs) { ptrdiff_t top = CG_OFFSET(cg); @@ -4629,7 +4596,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS } break; case TOK_DOT: - if (!js_EmitTree(cx, cg, lhs->expr())) + if (!EmitTree(cx, cg, lhs->expr())) return false; offset++; if (!cg->makeAtomIndex(lhs->pn_atom, &atomIndex)) @@ -4637,9 +4604,9 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS break; case TOK_LB: JS_ASSERT(lhs->isArity(PN_BINARY)); - if (!js_EmitTree(cx, cg, lhs->pn_left)) + if (!EmitTree(cx, cg, lhs->pn_left)) return false; - if (!js_EmitTree(cx, cg, lhs->pn_right)) + if (!EmitTree(cx, cg, lhs->pn_right)) return false; offset += 2; break; @@ -4649,16 +4616,16 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS break; #endif case TOK_LP: - if (!js_EmitTree(cx, cg, lhs)) + if (!EmitTree(cx, cg, lhs)) return false; offset++; break; #if JS_HAS_XML_SUPPORT case TOK_UNARYOP: JS_ASSERT(lhs->isOp(JSOP_SETXMLNAME)); - if (!js_EmitTree(cx, cg, lhs->pn_kid)) + if (!EmitTree(cx, cg, lhs->pn_kid)) return false; - if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) + if (Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) return false; offset++; break; @@ -4673,13 +4640,13 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS case TOK_NAME: if (lhs->isConst()) { if (lhs->isOp(JSOP_CALLEE)) { - if (js_Emit1(cx, cg, JSOP_CALLEE) < 0) + if (Emit1(cx, cg, JSOP_CALLEE) < 0) return false; } else { EMIT_INDEX_OP(lhs->getOp(), atomIndex); } } else if (lhs->isOp(JSOP_SETNAME)) { - if (js_Emit1(cx, cg, JSOP_DUP) < 0) + if (Emit1(cx, cg, JSOP_DUP) < 0) return false; EMIT_INDEX_OP(JSOP_GETXPROP, atomIndex); } else if (lhs->isOp(JSOP_SETGNAME)) { @@ -4691,7 +4658,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS } break; case TOK_DOT: - if (js_Emit1(cx, cg, JSOP_DUP) < 0) + if (Emit1(cx, cg, JSOP_DUP) < 0) return false; if (lhs->pn_atom == cx->runtime->atomState.protoAtom) { if (!EmitIndexOp(cx, JSOP_QNAMEPART, atomIndex, cg)) @@ -4708,7 +4675,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS #if JS_HAS_XML_SUPPORT case TOK_UNARYOP: #endif - if (js_Emit1(cx, cg, JSOP_DUP2) < 0) + if (Emit1(cx, cg, JSOP_DUP2) < 0) return false; if (!EmitElemOpBase(cx, cg, JSOP_GETELEM)) return false; @@ -4719,11 +4686,11 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS /* Now emit the right operand (it may affect the namespace). */ if (rhs) { - if (!js_EmitTree(cx, cg, rhs)) + if (!EmitTree(cx, cg, rhs)) return false; } else { /* The value to assign is the next enumeration value in a for-in loop. */ - if (js_Emit2(cx, cg, JSOP_ITERNEXT, offset) < 0) + if (Emit2(cx, cg, JSOP_ITERNEXT, offset) < 0) return false; } @@ -4735,10 +4702,10 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS * a bit further below) we will avoid emitting the assignment op. */ if (!lhs->isKind(TOK_NAME) || !lhs->isConst()) { - if (js_NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0) + if (NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0) return false; } - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return false; } @@ -4748,7 +4715,8 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS !lhs->isKind(TOK_RB) && !lhs->isKind(TOK_RC) && #endif - js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) { + NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) + { return false; } @@ -4769,7 +4737,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS break; case TOK_LB: case TOK_LP: - if (js_Emit1(cx, cg, JSOP_SETELEM) < 0) + if (Emit1(cx, cg, JSOP_SETELEM) < 0) return false; break; #if JS_HAS_DESTRUCTURING @@ -4781,7 +4749,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS #endif #if JS_HAS_XML_SUPPORT case TOK_UNARYOP: - if (js_Emit1(cx, cg, JSOP_SETXMLNAME) < 0) + if (Emit1(cx, cg, JSOP_SETXMLNAME) < 0) return false; break; #endif @@ -4793,7 +4761,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS #if defined DEBUG_brendan || defined DEBUG_mrbkap static JSBool -GettableNoteForNextOp(JSCodeGenerator *cg) +GettableNoteForNextOp(CodeGenerator *cg) { ptrdiff_t offset, target; jssrcnote *sn, *end; @@ -4812,16 +4780,16 @@ GettableNoteForNextOp(JSCodeGenerator *cg) /* Top-level named functions need a nop for decompilation. */ static JSBool -EmitFunctionDefNop(JSContext *cx, JSCodeGenerator *cg, uintN index) +EmitFunctionDefNop(JSContext *cx, CodeGenerator *cg, uintN index) { - return js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index) >= 0 && - js_Emit1(cx, cg, JSOP_NOP) >= 0; + return NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index) >= 0 && + Emit1(cx, cg, JSOP_NOP) >= 0; } static bool -EmitNewInit(JSContext *cx, JSCodeGenerator *cg, JSProtoKey key, JSParseNode *pn, int sharpnum) +EmitNewInit(JSContext *cx, CodeGenerator *cg, JSProtoKey key, ParseNode *pn, int sharpnum) { - if (js_Emit3(cx, cg, JSOP_NEWINIT, (jsbytecode) key, 0) < 0) + if (Emit3(cx, cg, JSOP_NEWINIT, (jsbytecode) key, 0) < 0) return false; #if JS_HAS_SHARP_VARS if (cg->hasSharps()) { @@ -4837,18 +4805,20 @@ EmitNewInit(JSContext *cx, JSCodeGenerator *cg, JSProtoKey key, JSParseNode *pn, } static bool -EmitEndInit(JSContext *cx, JSCodeGenerator *cg, uint32 count) +EmitEndInit(JSContext *cx, CodeGenerator *cg, uint32 count) { #if JS_HAS_SHARP_VARS /* Emit an op for sharp array cleanup and decompilation. */ if (cg->hasSharps() && count != 0) EMIT_UINT16_IMM_OP(JSOP_SHARPINIT, cg->sharpSlotBase); #endif - return js_Emit1(cx, cg, JSOP_ENDINIT) >= 0; + return Emit1(cx, cg, JSOP_ENDINIT) >= 0; } +} /* namespace frontend */ + bool -JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) +ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) { switch (getKind()) { case TOK_NUMBER: @@ -4880,11 +4850,11 @@ JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) return false; unsigned idx = 0; - for (JSParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) { + for (ParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) { Value value; if (!pn->getConstantValue(cx, strictChecks, &value)) return false; - if (!obj->defineProperty(cx, INT_TO_JSID(idx), value, NULL, NULL, JSPROP_ENUMERATE)) + if (!obj->defineGeneric(cx, INT_TO_JSID(idx), value, NULL, NULL, JSPROP_ENUMERATE)) return false; } JS_ASSERT(idx == pn_count); @@ -4901,12 +4871,12 @@ JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) if (!obj) return false; - for (JSParseNode *pn = pn_head; pn; pn = pn->pn_next) { + for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) { Value value; if (!pn->pn_right->getConstantValue(cx, strictChecks, &value)) return false; - JSParseNode *pnid = pn->pn_left; + ParseNode *pnid = pn->pn_left; if (pnid->isKind(TOK_NUMBER)) { Value idvalue = NumberValue(pnid->pn_dval); jsid id; @@ -4914,7 +4884,7 @@ JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) id = INT_TO_JSID(idvalue.toInt32()); else if (!js_InternNonIntElementId(cx, obj, idvalue, &id)) return false; - if (!obj->defineProperty(cx, id, value, NULL, NULL, JSPROP_ENUMERATE)) + if (!obj->defineGeneric(cx, id, value, NULL, NULL, JSPROP_ENUMERATE)) return false; } else { JS_ASSERT(pnid->isKind(TOK_NAME) || @@ -4938,15 +4908,17 @@ JSParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp) return false; } +namespace frontend { + static bool -EmitSingletonInitialiser(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitSingletonInitialiser(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { Value value; if (!pn->getConstantValue(cx, cg->needStrictChecks(), &value)) return false; JS_ASSERT(value.isObject()); - JSObjectBox *objbox = cg->parser->newObjectBox(&value.toObject()); + ObjectBox *objbox = cg->parser->newObjectBox(&value.toObject()); if (!objbox) return false; @@ -4959,17 +4931,14 @@ JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1); class EmitLevelManager { -private: - JSCodeGenerator *cg; - -public: - EmitLevelManager(JSCodeGenerator *cg) : cg(cg) { cg->emitLevel++; } - + CodeGenerator *cg; + public: + EmitLevelManager(CodeGenerator *cg) : cg(cg) { cg->emitLevel++; } ~EmitLevelManager() { cg->emitLevel--; } }; static bool -EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitCatch(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { ptrdiff_t catchStart, guardJump; @@ -4977,7 +4946,7 @@ EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Morph STMT_BLOCK to STMT_CATCH, note the block entry code offset, * and save the block object atom. */ - JSStmtInfo *stmt = cg->topStmt; + StmtInfo *stmt = cg->topStmt; JS_ASSERT(stmt->type == STMT_BLOCK && (stmt->flags & SIF_SCOPE)); stmt->type = STMT_CATCH; catchStart = stmt->update; @@ -4987,24 +4956,24 @@ EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(stmt->type == STMT_TRY || stmt->type == STMT_FINALLY); /* Pick up the pending exception and bind it to the catch variable. */ - if (js_Emit1(cx, cg, JSOP_EXCEPTION) < 0) + if (Emit1(cx, cg, JSOP_EXCEPTION) < 0) return false; /* * Dup the exception object if there is a guard for rethrowing to use * it later when rethrowing or in other catches. */ - if (pn->pn_kid2 && js_Emit1(cx, cg, JSOP_DUP) < 0) + if (pn->pn_kid2 && Emit1(cx, cg, JSOP_DUP) < 0) return false; - JSParseNode *pn2 = pn->pn_kid1; + ParseNode *pn2 = pn->pn_kid1; switch (pn2->getKind()) { #if JS_HAS_DESTRUCTURING case TOK_RB: case TOK_RC: if (!EmitDestructuringOps(cx, cg, JSOP_NOP, pn2)) return false; - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return false; break; #endif @@ -5021,12 +4990,10 @@ EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Emit the guard expression, if there is one. */ if (pn->pn_kid2) { - if (!js_EmitTree(cx, cg, pn->pn_kid2)) + if (!EmitTree(cx, cg, pn->pn_kid2)) return false; - if (!js_SetSrcNoteOffset(cx, cg, CATCHNOTE(*stmt), 0, - CG_OFFSET(cg) - catchStart)) { + if (!SetSrcNoteOffset(cx, cg, CATCHNOTE(*stmt), 0, CG_OFFSET(cg) - catchStart)) return false; - } /* ifeq */ guardJump = EmitJump(cx, cg, JSOP_IFEQ, 0); if (guardJump < 0) @@ -5034,12 +5001,12 @@ EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) GUARDJUMP(*stmt) = guardJump; /* Pop duplicated exception object as we no longer need it. */ - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return false; } /* Emit the catch body. */ - if (!js_EmitTree(cx, cg, pn->pn_kid3)) + if (!EmitTree(cx, cg, pn->pn_kid3)) return false; /* @@ -5047,15 +5014,15 @@ EmitCatch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * our TOK_LEXICALSCOPE parent, so the decompiler knows to pop. */ ptrdiff_t off = cg->stackDepth; - if (js_NewSrcNote2(cx, cg, SRC_CATCH, off) < 0) + if (NewSrcNote2(cx, cg, SRC_CATCH, off) < 0) return false; return true; } static bool -EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitTry(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { - JSStmtInfo stmtInfo; + StmtInfo stmtInfo; ptrdiff_t catchJump = -1; /* @@ -5067,7 +5034,7 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * being written into the bytecode stream and fixed-up later (c.f. * EmitBackPatchOp and BackPatch). */ - js_PushStatement(cg, &stmtInfo, pn->pn_kid3 ? STMT_FINALLY : STMT_TRY, CG_OFFSET(cg)); + PushStatement(cg, &stmtInfo, pn->pn_kid3 ? STMT_FINALLY : STMT_TRY, CG_OFFSET(cg)); /* * Since an exception can be thrown at any place inside the try block, @@ -5081,33 +5048,33 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) intN depth = cg->stackDepth; /* Mark try location for decompilation, then emit try block. */ - if (js_Emit1(cx, cg, JSOP_TRY) < 0) + if (Emit1(cx, cg, JSOP_TRY) < 0) return false; ptrdiff_t tryStart = CG_OFFSET(cg); - if (!js_EmitTree(cx, cg, pn->pn_kid1)) + if (!EmitTree(cx, cg, pn->pn_kid1)) return false; JS_ASSERT(depth == cg->stackDepth); /* GOSUB to finally, if present. */ if (pn->pn_kid3) { - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return false; if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(stmtInfo)) < 0) return false; } /* Emit (hidden) jump over catch and/or finally. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return false; if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump) < 0) return false; ptrdiff_t tryEnd = CG_OFFSET(cg); - JSObjectBox *prevBox = NULL; + ObjectBox *prevBox = NULL; /* If this try has a catch block, emit it. */ - JSParseNode *lastCatch = NULL; - if (JSParseNode *pn2 = pn->pn_kid2) { + ParseNode *lastCatch = NULL; + if (ParseNode *pn2 = pn->pn_kid2) { uintN count = 0; /* previous catch block's population */ /* @@ -5133,7 +5100,7 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * also used for the catch-all trynote for capturing exceptions * thrown from catch{} blocks. */ - for (JSParseNode *pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { + for (ParseNode *pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { ptrdiff_t guardJump, catchNote; JS_ASSERT(cg->stackDepth == depth); @@ -5158,11 +5125,11 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * since it compensates for the hidden JSOP_DUP at the * start of the previous guarded catch. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_THROWING) < 0) { + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || + Emit1(cx, cg, JSOP_THROWING) < 0) { return false; } - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return false; if (!EmitLeaveBlock(cx, cg, JSOP_LEAVEBLOCK, prevBox)) return false; @@ -5171,12 +5138,12 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * Annotate the JSOP_ENTERBLOCK that's about to be generated - * by the call to js_EmitTree immediately below. Save this + * by the call to EmitTree immediately below. Save this * source note's index in stmtInfo for use by the TOK_CATCH: * case, where the length of the catch guard is set as the * note's offset. */ - catchNote = js_NewSrcNote2(cx, cg, SRC_CATCH, 0); + catchNote = NewSrcNote2(cx, cg, SRC_CATCH, 0); if (catchNote < 0) return false; CATCHNOTE(stmtInfo) = catchNote; @@ -5189,7 +5156,7 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(pn3->isKind(TOK_LEXICALSCOPE)); count = OBJ_BLOCK_COUNT(cx, pn3->pn_objbox->object); prevBox = pn3->pn_objbox; - if (!js_EmitTree(cx, cg, pn3)) + if (!EmitTree(cx, cg, pn3)) return false; /* gosub , if required */ @@ -5203,7 +5170,7 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Jump over the remaining catch blocks. This will get fixed * up to jump to after catch/finally. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return false; if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump) < 0) return false; @@ -5236,10 +5203,8 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Rethrow the exception, delegating executing of finally if any * to the exception handler. */ - if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || - js_Emit1(cx, cg, JSOP_THROW) < 0) { + if (NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || Emit1(cx, cg, JSOP_THROW) < 0) return false; - } if (EmitBlockChain(cx, cg) < 0) return false; @@ -5263,17 +5228,18 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) stmtInfo.type = STMT_SUBROUTINE; if (!UpdateLineNumberNotes(cx, cg, pn->pn_kid3->pn_pos.begin.lineno)) return false; - if (js_Emit1(cx, cg, JSOP_FINALLY) < 0 || - !js_EmitTree(cx, cg, pn->pn_kid3) || - js_Emit1(cx, cg, JSOP_RETSUB) < 0) { + if (Emit1(cx, cg, JSOP_FINALLY) < 0 || + !EmitTree(cx, cg, pn->pn_kid3) || + Emit1(cx, cg, JSOP_RETSUB) < 0) + { return false; } JS_ASSERT(cg->stackDepth == depth); } - if (!js_PopStatementCG(cx, cg)) + if (!PopStatementCG(cx, cg)) return false; - if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0) + if (NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || Emit1(cx, cg, JSOP_NOP) < 0) return false; /* Fix up the end-of-try/catch jumps to come here. */ @@ -5299,9 +5265,9 @@ EmitTry(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } static bool -EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitIf(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { - JSStmtInfo stmtInfo; + StmtInfo stmtInfo; /* Initialize so we can detect else-if chains and avoid recursion. */ stmtInfo.type = STMT_IF; @@ -5311,11 +5277,11 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if_again: /* Emit code for the condition before pushing stmtInfo. */ - if (!js_EmitTree(cx, cg, pn->pn_kid1)) + if (!EmitTree(cx, cg, pn->pn_kid1)) return JS_FALSE; ptrdiff_t top = CG_OFFSET(cg); if (stmtInfo.type == STMT_IF) { - js_PushStatement(cg, &stmtInfo, STMT_IF, top); + PushStatement(cg, &stmtInfo, STMT_IF, top); } else { /* * We came here from the goto further below that detects else-if @@ -5329,15 +5295,15 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(stmtInfo.type == STMT_ELSE); stmtInfo.type = STMT_IF; stmtInfo.update = top; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) return JS_FALSE; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1, top - beq)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 1, top - beq)) return JS_FALSE; } /* Emit an annotated branch-if-false around the then part. */ - JSParseNode *pn3 = pn->pn_kid3; - noteIndex = js_NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF); + ParseNode *pn3 = pn->pn_kid3; + noteIndex = NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF); if (noteIndex < 0) return JS_FALSE; beq = EmitJump(cx, cg, JSOP_IFEQ, 0); @@ -5345,7 +5311,7 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; /* Emit code for the then and optional else parts. */ - if (!js_EmitTree(cx, cg, pn->pn_kid2)) + if (!EmitTree(cx, cg, pn->pn_kid2)) return JS_FALSE; if (pn3) { /* Modify stmtInfo so we know we're in the else part. */ @@ -5353,8 +5319,8 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * Emit a JSOP_BACKPATCH op to jump from the end of our then part - * around the else part. The js_PopStatementCG call at the bottom - * of this function will fix up the backpatch chain linked from + * around the else part. The PopStatementCG call at the bottom of this + * function will fix up the backpatch chain linked from * stmtInfo.breaks. */ jmp = EmitGoto(cx, cg, &stmtInfo, &stmtInfo.breaks); @@ -5368,7 +5334,7 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) goto if_again; } - if (!js_EmitTree(cx, cg, pn3)) + if (!EmitTree(cx, cg, pn3)) return JS_FALSE; /* @@ -5378,18 +5344,18 @@ EmitIf(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * jump was required to leap from the end of the then clause over * the else clause. */ - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) return JS_FALSE; } else { /* No else part, fixup the branch-if-false to come here. */ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq); } - return js_PopStatementCG(cx, cg); + return PopStatementCG(cx, cg); } #if JS_HAS_BLOCK_SCOPE static bool -EmitLet(JSContext *cx, JSCodeGenerator *cg, JSParseNode *&pn) +EmitLet(JSContext *cx, CodeGenerator *cg, ParseNode *&pn) { /* * pn represents one of these syntactic constructs: @@ -5402,7 +5368,7 @@ EmitLet(JSContext *cx, JSCodeGenerator *cg, JSParseNode *&pn) * with their variable declarations on the left and the body on the * right. */ - JSParseNode *pn2; + ParseNode *pn2; if (pn->isArity(PN_BINARY)) { pn2 = pn->pn_right; pn = pn->pn_left; @@ -5432,10 +5398,10 @@ EmitLet(JSContext *cx, JSCodeGenerator *cg, JSParseNode *&pn) return false; /* Thus non-null pn2 is the body of the let block or expression. */ - if (pn2 && !js_EmitTree(cx, cg, pn2)) + if (pn2 && !EmitTree(cx, cg, pn2)) return false; - if (noteIndex >= 0 && !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - tmp)) + if (noteIndex >= 0 && !SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - tmp)) return false; return true; @@ -5444,9 +5410,9 @@ EmitLet(JSContext *cx, JSCodeGenerator *cg, JSParseNode *&pn) #if JS_HAS_XML_SUPPORT static bool -EmitXMLTag(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitXMLTag(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { - if (js_Emit1(cx, cg, JSOP_STARTXML) < 0) + if (Emit1(cx, cg, JSOP_STARTXML) < 0) return false; { @@ -5459,30 +5425,26 @@ EmitXMLTag(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } JS_ASSERT(pn->pn_count != 0); - JSParseNode *pn2 = pn->pn_head; - if (pn2->isKind(TOK_LC) && js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) + ParseNode *pn2 = pn->pn_head; + if (pn2->isKind(TOK_LC) && Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) return false; - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return false; - if (js_Emit1(cx, cg, JSOP_ADD) < 0) + if (Emit1(cx, cg, JSOP_ADD) < 0) return false; uint32 i; for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) { - if (pn2->isKind(TOK_LC) && - js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { + if (pn2->isKind(TOK_LC) && Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) return false; - } - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return false; if ((i & 1) && pn2->isKind(TOK_LC)) { - if (js_Emit1(cx, cg, JSOP_TOATTRVAL) < 0) + if (Emit1(cx, cg, JSOP_TOATTRVAL) < 0) return false; } - if (js_Emit1(cx, cg, - (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) { + if (Emit1(cx, cg, (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) return false; - } } { @@ -5493,17 +5455,17 @@ EmitXMLTag(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return false; EMIT_INDEX_OP(JSOP_STRING, index); } - if (js_Emit1(cx, cg, JSOP_ADD) < 0) + if (Emit1(cx, cg, JSOP_ADD) < 0) return false; - if ((pn->pn_xflags & PNX_XMLROOT) && js_Emit1(cx, cg, pn->getOp()) < 0) + if ((pn->pn_xflags & PNX_XMLROOT) && Emit1(cx, cg, pn->getOp()) < 0) return false; return true; } static bool -EmitXMLProcessingInstruction(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitXMLProcessingInstruction(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { jsatomid index; if (!cg->makeAtomIndex(pn->pn_pidata, &index)) @@ -5517,12 +5479,12 @@ EmitXMLProcessingInstruction(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn #endif static bool -EmitLexicalScope(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSBool &ok) +EmitLexicalScope(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSBool &ok) { - JSStmtInfo stmtInfo; - JSStmtInfo *stmt; - JSObjectBox *objbox = pn->pn_objbox; - js_PushBlockScope(cg, &stmtInfo, objbox, CG_OFFSET(cg)); + StmtInfo stmtInfo; + StmtInfo *stmt; + ObjectBox *objbox = pn->pn_objbox; + PushBlockScope(cg, &stmtInfo, objbox, CG_OFFSET(cg)); /* * If this lexical scope is not for a catch block, let block or let @@ -5544,7 +5506,7 @@ EmitLexicalScope(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSBool &ok CG_LAST_NOTE_OFFSET(cg) != CG_OFFSET(cg) || !GettableNoteForNextOp(cg)); #endif - noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0); + noteIndex = NewSrcNote2(cx, cg, SRC_BRACE, 0); if (noteIndex < 0) return false; } @@ -5553,63 +5515,60 @@ EmitLexicalScope(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSBool &ok if (!EmitEnterBlock(cx, pn, cg)) return false; - if (!js_EmitTree(cx, cg, pn->pn_expr)) + if (!EmitTree(cx, cg, pn->pn_expr)) return false; JSOp op = pn->getOp(); if (op == JSOP_LEAVEBLOCKEXPR) { - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) return false; } else { - if (noteIndex >= 0 && - !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, - CG_OFFSET(cg) - top)) { + if (noteIndex >= 0 && !SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - top)) return false; - } } /* Emit the JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR opcode. */ if (!EmitLeaveBlock(cx, cg, op, objbox)) return false; - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); return true; } static bool -EmitWith(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSBool &ok) +EmitWith(JSContext *cx, CodeGenerator *cg, ParseNode *pn, JSBool &ok) { - JSStmtInfo stmtInfo; - if (!js_EmitTree(cx, cg, pn->pn_left)) + StmtInfo stmtInfo; + if (!EmitTree(cx, cg, pn->pn_left)) return false; - js_PushStatement(cg, &stmtInfo, STMT_WITH, CG_OFFSET(cg)); - if (js_Emit1(cx, cg, JSOP_ENTERWITH) < 0) + PushStatement(cg, &stmtInfo, STMT_WITH, CG_OFFSET(cg)); + if (Emit1(cx, cg, JSOP_ENTERWITH) < 0) return false; /* Make blockChain determination quicker. */ if (EmitBlockChain(cx, cg) < 0) return false; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return false; - if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0) + if (Emit1(cx, cg, JSOP_LEAVEWITH) < 0) return false; - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); return true; } JSBool -js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) +EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn) { JSBool useful, wantval; - JSStmtInfo stmtInfo; - JSStmtInfo *stmt; + StmtInfo stmtInfo; + StmtInfo *stmt; ptrdiff_t top, off, tmp, beq, jmp, tmp2, tmp3; - JSParseNode *pn2, *pn3; + ParseNode *pn2, *pn3; JSAtom *atom; jsatomid atomIndex; uintN index; ptrdiff_t noteIndex, noteIndex2; - JSSrcNoteType noteType; + SrcNoteType noteType; jsbytecode *pc; JSOp op; uint32 argc; @@ -5634,7 +5593,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) #if JS_HAS_XML_SUPPORT if (pn->isArity(PN_NULLARY)) { - if (js_Emit1(cx, cg, JSOP_GETFUNNS) < 0) + if (Emit1(cx, cg, JSOP_GETFUNNS) < 0) return JS_FALSE; break; } @@ -5659,7 +5618,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) fun->kind() == JSFUN_INTERPRETED); /* Generate code for the function's body. */ - JSCodeGenerator *cg2 = cx->new_(cg->parser, pn->pn_pos.begin.lineno); + CodeGenerator *cg2 = cx->new_(cg->parser, pn->pn_pos.begin.lineno); if (!cg2) { js_ReportOutOfMemory(cx); return JS_FALSE; @@ -5682,15 +5641,16 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) cg2->parent = cg; /* - * jsparse.cpp:SetStaticLevel limited static nesting depth to fit in 16 - * bits and to reserve the all-ones value, thereby reserving the magic - * FREE_UPVAR_COOKIE value. Note the cg2->staticLevel assignment below. + * js::frontend::SetStaticLevel limited static nesting depth to fit in + * 16 bits and to reserve the all-ones value, thereby reserving the + * magic FREE_UPVAR_COOKIE value. Note the cg2->staticLevel assignment + * below. */ JS_ASSERT(cg->staticLevel < JS_BITMASK(16) - 1); cg2->staticLevel = cg->staticLevel + 1; /* We measured the max scope depth when we parsed the function. */ - if (!js_EmitFunctionScript(cx, cg2, pn->pn_body)) + if (!EmitFunctionScript(cx, cg2, pn->pn_body)) pn = NULL; cx->delete_(cg2); @@ -5705,7 +5665,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) op = pn->getOp(); if (op != JSOP_NOP) { if ((pn->pn_funbox->tcflags & TCF_GENEXP_LAMBDA) && - js_NewSrcNote(cx, cg, SRC_GENEXP) < 0) { + NewSrcNote(cx, cg, SRC_GENEXP) < 0) + { return JS_FALSE; } EMIT_INDEX_OP(op, index); @@ -5722,7 +5683,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * names in the variable object before the already-generated main code * is executed. This extra work for top-level scripts is not necessary * when we emit the code for a function. It is fully parsed prior to - * invocation of the emitter and calls to js_EmitTree for function + * invocation of the emitter and calls to EmitTree for function * definitions can be scheduled before generating the rest of code. */ if (!cg->inFunction()) { @@ -5766,8 +5727,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_ARGSBODY: { - JSParseNode *pnlast = pn->last(); - for (JSParseNode *pn2 = pn->pn_head; pn2 != pnlast; pn2 = pn2->pn_next) { + ParseNode *pnlast = pn->last(); + for (ParseNode *pn2 = pn->pn_head; pn2 != pnlast; pn2 = pn2->pn_next) { if (!pn2->isDefn()) continue; if (!BindNameToSlot(cx, cg, pn2)) @@ -5777,14 +5738,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; } } - ok = js_EmitTree(cx, cg, pnlast); + ok = EmitTree(cx, cg, pnlast); break; } case TOK_UPVARS: JS_ASSERT(pn->pn_names->count() != 0); cg->roLexdeps = pn->pn_names; - ok = js_EmitTree(cx, cg, pn->pn_tree); + ok = EmitTree(cx, cg, pn->pn_tree); cg->roLexdeps.clearMap(); pn->pn_names.releaseMap(cx); break; @@ -5812,29 +5773,29 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * N N*(ifeq-fail; goto); ifeq-pass goto; N*ifne-pass; ifne-fail * * SpiderMonkey, pre-mozilla.org, emitted while parsing and so used - * test at the top. When JSParseNode trees were added during the ES3 + * test at the top. When ParseNode trees were added during the ES3 * work (1998-9), the code generation scheme was not optimized, and * the decompiler continued to take advantage of the branch and jump * that bracketed the body. But given the SRC_WHILE note, it is easy * to support the more efficient scheme. */ - js_PushStatement(cg, &stmtInfo, STMT_WHILE_LOOP, top); - noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE); + PushStatement(cg, &stmtInfo, STMT_WHILE_LOOP, top); + noteIndex = NewSrcNote(cx, cg, SRC_WHILE); if (noteIndex < 0) return JS_FALSE; jmp = EmitJump(cx, cg, JSOP_GOTO, 0); if (jmp < 0) return JS_FALSE; - noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + noteIndex2 = NewSrcNote(cx, cg, SRC_TRACE); if (noteIndex2 < 0) return JS_FALSE; top = EmitTraceOp(cx, cg, pn->pn_right); if (top < 0) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - if (!js_EmitTree(cx, cg, pn->pn_left)) + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)); if (beq < 0) @@ -5843,20 +5804,20 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex * note gets bigger. */ - if (!js_SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) + if (!SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) return JS_FALSE; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, beq - jmp)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 0, beq - jmp)) return JS_FALSE; - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); break; case TOK_DO: /* Emit an annotated nop so we know to decompile a 'do' keyword. */ - noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE); - if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0) + noteIndex = NewSrcNote(cx, cg, SRC_WHILE); + if (noteIndex < 0 || Emit1(cx, cg, JSOP_NOP) < 0) return JS_FALSE; - noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + noteIndex2 = NewSrcNote(cx, cg, SRC_TRACE); if (noteIndex2 < 0) return JS_FALSE; @@ -5864,8 +5825,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) top = EmitTraceOp(cx, cg, pn->pn_left); if (top < 0) return JS_FALSE; - js_PushStatement(cg, &stmtInfo, STMT_DO_LOOP, top); - if (!js_EmitTree(cx, cg, pn->pn_left)) + PushStatement(cg, &stmtInfo, STMT_DO_LOOP, top); + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; /* Set loop and enclosing label update offsets, for continue. */ @@ -5876,7 +5837,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL); /* Compile the loop condition, now that continues know where to go. */ - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; /* @@ -5891,18 +5852,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex * note gets bigger. */ - if (!js_SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) + if (!SetSrcNoteOffset(cx, cg, noteIndex2, 0, beq - top)) return JS_FALSE; - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, 1 + (off - top))) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 0, 1 + (off - top))) return JS_FALSE; - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); break; case TOK_FOR: beq = 0; /* suppress gcc warnings */ jmp = -1; pn2 = pn->pn_left; - js_PushStatement(cg, &stmtInfo, STMT_FOR_LOOP, top); + PushStatement(cg, &stmtInfo, STMT_FOR_LOOP, top); if (pn2->isKind(TOK_IN)) { /* Set stmtInfo type for later testing. */ @@ -5916,11 +5877,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * banned. */ bool forLet = false; - if (JSParseNode *decl = pn2->pn_kid1) { + if (ParseNode *decl = pn2->pn_kid1) { JS_ASSERT(TokenKindIsDecl(decl->getKind())); forLet = decl->isKind(TOK_LET); cg->flags |= TCF_IN_FOR_INIT; - if (!js_EmitTree(cx, cg, decl)) + if (!EmitTree(cx, cg, decl)) return JS_FALSE; cg->flags &= ~TCF_IN_FOR_INIT; } @@ -5930,7 +5891,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) TempPopScope tps; if (forLet && !tps.popBlock(cx, cg)) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn2->pn_kid3)) + if (!EmitTree(cx, cg, pn2->pn_kid3)) return JS_FALSE; if (forLet && !tps.repushBlock(cx, cg)) return JS_FALSE; @@ -5942,11 +5903,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * destructuring for-in). */ JS_ASSERT(pn->isOp(JSOP_ITER)); - if (js_Emit2(cx, cg, JSOP_ITER, (uint8) pn->pn_iflags) < 0) + if (Emit2(cx, cg, JSOP_ITER, (uint8) pn->pn_iflags) < 0) return JS_FALSE; /* Annotate so the decompiler can find the loop-closing jump. */ - noteIndex = js_NewSrcNote(cx, cg, SRC_FOR_IN); + noteIndex = NewSrcNote(cx, cg, SRC_FOR_IN); if (noteIndex < 0) return JS_FALSE; @@ -5958,7 +5919,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (jmp < 0) return JS_FALSE; - noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + noteIndex2 = NewSrcNote(cx, cg, SRC_TRACE); if (noteIndex2 < 0) return JS_FALSE; @@ -5980,20 +5941,20 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!EmitAssignment(cx, cg, pn2->pn_kid2, JSOP_NOP, NULL)) return false; tmp2 = CG_OFFSET(cg); - if (pn2->pn_kid1 && js_NewSrcNote2(cx, cg, SRC_DECL, - (pn2->pn_kid1->isOp(JSOP_DEFVAR)) - ? SRC_DECL_VAR - : SRC_DECL_LET) < 0) { + if (pn2->pn_kid1 && NewSrcNote2(cx, cg, SRC_DECL, (pn2->pn_kid1->isOp(JSOP_DEFVAR)) + ? SRC_DECL_VAR + : SRC_DECL_LET) < 0) + { return false; } - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return false; /* The stack should be balanced around the assignment opcode sequence. */ JS_ASSERT(cg->stackDepth == loopDepth); /* Emit code for the loop body. */ - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; /* Set loop and enclosing "update" offsets, for continue. */ @@ -6006,7 +5967,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Fixup the goto that starts the loop to jump down to JSOP_MOREITER. */ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - if (js_Emit1(cx, cg, JSOP_MOREITER) < 0) + if (Emit1(cx, cg, JSOP_MOREITER) < 0) return JS_FALSE; beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)); if (beq < 0) @@ -6016,13 +5977,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex * note gets bigger. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, beq - top)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, beq - top)) return JS_FALSE; /* Set the first srcnote offset so we can find the start of the loop body. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp2 - jmp)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp2 - jmp)) return JS_FALSE; /* Set the second srcnote offset so we can find the closing jump. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, beq - jmp)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, beq - jmp)) return JS_FALSE; } else { /* C-style for (init; cond; update) ... loop. */ @@ -6040,7 +6001,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } #endif if (op == JSOP_POP) { - if (!js_EmitTree(cx, cg, pn3)) + if (!EmitTree(cx, cg, pn3)) return JS_FALSE; if (TokenKindIsDecl(pn3->getKind())) { /* @@ -6063,8 +6024,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * from the top local variable by the length of the JSOP_GOTO{,X} * emitted in between tmp and top if this loop has a condition. */ - noteIndex = js_NewSrcNote(cx, cg, SRC_FOR); - if (noteIndex < 0 || js_Emit1(cx, cg, op) < 0) + noteIndex = NewSrcNote(cx, cg, SRC_FOR); + if (noteIndex < 0 || Emit1(cx, cg, op) < 0) return JS_FALSE; tmp = CG_OFFSET(cg); @@ -6078,14 +6039,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) top = CG_OFFSET(cg); SET_STATEMENT_TOP(&stmtInfo, top); - noteIndex2 = js_NewSrcNote(cx, cg, SRC_TRACE); + noteIndex2 = NewSrcNote(cx, cg, SRC_TRACE); if (noteIndex2 < 0) return JS_FALSE; /* Emit code for the loop body. */ if (EmitTraceOp(cx, cg, pn->pn_right) < 0) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; /* Set the second note offset so we can find the update part. */ @@ -6108,17 +6069,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; } #endif - if (op == JSOP_POP && !js_EmitTree(cx, cg, pn3)) + if (op == JSOP_POP && !EmitTree(cx, cg, pn3)) return JS_FALSE; /* Always emit the POP or NOP, to help the decompiler. */ - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; /* Restore the absolute line number for source note readers. */ off = (ptrdiff_t) pn->pn_pos.end.lineno; if (CG_CURRENT_LINE(cg) != (uintN) off) { - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0) + if (NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0) return JS_FALSE; CG_CURRENT_LINE(cg) = (uintN) off; } @@ -6131,7 +6092,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(jmp >= 0); CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - if (!js_EmitTree(cx, cg, pn2->pn_kid2)) + if (!EmitTree(cx, cg, pn2->pn_kid2)) return JS_FALSE; } @@ -6139,24 +6100,16 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex * note gets bigger. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, - CG_OFFSET(cg) - top)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex2, 0, CG_OFFSET(cg) - top)) return JS_FALSE; - } /* Set the first note offset so we can find the loop condition. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, - tmp3 - tmp)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp3 - tmp)) return JS_FALSE; - } - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, - tmp2 - tmp)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, tmp2 - tmp)) return JS_FALSE; - } /* The third note offset helps us find the loop-closing jump. */ - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2, - CG_OFFSET(cg) - tmp)) { + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2, CG_OFFSET(cg) - tmp)) return JS_FALSE; - } if (pn2->pn_kid2) { beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg)); @@ -6171,12 +6124,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } /* Now fixup all breaks and continues (before for/in's JSOP_ENDITER). */ - if (!js_PopStatementCG(cx, cg)) + if (!PopStatementCG(cx, cg)) return JS_FALSE; if (pn2->isKind(TOK_IN)) { if (!NewTryNote(cx, cg, JSTRY_ITER, cg->stackDepth, top, CG_OFFSET(cg)) || - js_Emit1(cx, cg, JSOP_ENDITER) < 0) { + Emit1(cx, cg, JSOP_ENDITER) < 0) + { return JS_FALSE; } } @@ -6213,7 +6167,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) jsatomid labelIndex; if (atom) { /* Find the loop statement enclosed by the matching label. */ - JSStmtInfo *loop = NULL; + StmtInfo *loop = NULL; if (!cg->makeAtomIndex(atom, &labelIndex)) return JS_FALSE; while (stmt->type != STMT_LABEL || stmt->label != atom) { @@ -6259,10 +6213,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Push a return value */ pn2 = pn->pn_kid; if (pn2) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; } else { - if (js_Emit1(cx, cg, JSOP_PUSH) < 0) + if (Emit1(cx, cg, JSOP_PUSH) < 0) return JS_FALSE; } @@ -6278,13 +6232,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * extra JSOP_RETRVAL after the fixups. */ top = CG_OFFSET(cg); - if (js_Emit1(cx, cg, JSOP_RETURN) < 0) + if (Emit1(cx, cg, JSOP_RETURN) < 0) return JS_FALSE; if (!EmitNonLocalJumpFixup(cx, cg, NULL)) return JS_FALSE; if (top + JSOP_RETURN_LENGTH != CG_OFFSET(cg)) { CG_BASE(cg)[top] = JSOP_SETRVAL; - if (js_Emit1(cx, cg, JSOP_RETRVAL) < 0) + if (Emit1(cx, cg, JSOP_RETRVAL) < 0) return JS_FALSE; if (EmitBlockChain(cx, cg) < 0) return JS_FALSE; @@ -6295,15 +6249,15 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_YIELD: JS_ASSERT(cg->inFunction()); if (pn->pn_kid) { - if (!js_EmitTree(cx, cg, pn->pn_kid)) + if (!EmitTree(cx, cg, pn->pn_kid)) return JS_FALSE; } else { - if (js_Emit1(cx, cg, JSOP_PUSH) < 0) + if (Emit1(cx, cg, JSOP_PUSH) < 0) return JS_FALSE; } - if (pn->pn_hidden && js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0) + if (pn->pn_hidden && NewSrcNote(cx, cg, SRC_HIDDEN) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_YIELD) < 0) + if (Emit1(cx, cg, JSOP_YIELD) < 0) return JS_FALSE; break; #endif @@ -6312,9 +6266,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) { #if JS_HAS_XML_SUPPORT if (pn->isArity(PN_UNARY)) { - if (!js_EmitTree(cx, cg, pn->pn_kid)) + if (!EmitTree(cx, cg, pn->pn_kid)) return JS_FALSE; - if (js_Emit1(cx, cg, pn->getOp()) < 0) + if (Emit1(cx, cg, pn->getOp()) < 0) return JS_FALSE; break; } @@ -6325,14 +6279,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) noteIndex = -1; tmp = CG_OFFSET(cg); if (pn->pn_xflags & PNX_NEEDBRACES) { - noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0); - if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0) + noteIndex = NewSrcNote2(cx, cg, SRC_BRACE, 0); + if (noteIndex < 0 || Emit1(cx, cg, JSOP_NOP) < 0) return JS_FALSE; } - js_PushStatement(cg, &stmtInfo, STMT_BLOCK, top); + PushStatement(cg, &stmtInfo, STMT_BLOCK, top); - JSParseNode *pnchild = pn->pn_head; + ParseNode *pnchild = pn->pn_head; if (pn->pn_xflags & PNX_FUNCDEFS) { /* * This block contains top-level function definitions. To ensure @@ -6353,7 +6307,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) */ JS_ASSERT(pnchild->isKind(TOK_SEMI)); JS_ASSERT(pnchild->pn_kid->isKind(TOK_VAR)); - if (!js_EmitTree(cx, cg, pnchild)) + if (!EmitTree(cx, cg, pnchild)) return JS_FALSE; pnchild = pnchild->pn_next; } @@ -6361,7 +6315,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) for (pn2 = pnchild; pn2; pn2 = pn2->pn_next) { if (pn2->isKind(TOK_FUNCTION)) { if (pn2->isOp(JSOP_NOP)) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; } else { /* @@ -6376,28 +6330,25 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } } for (pn2 = pnchild; pn2; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; } - if (noteIndex >= 0 && - !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, - CG_OFFSET(cg) - tmp)) { + if (noteIndex >= 0 && !SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - tmp)) return JS_FALSE; - } - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); break; } case TOK_SEQ: JS_ASSERT(pn->isArity(PN_LIST)); - js_PushStatement(cg, &stmtInfo, STMT_SEQ, top); + PushStatement(cg, &stmtInfo, STMT_SEQ, top); for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; } - ok = js_PopStatementCG(cx, cg); + ok = PopStatementCG(cx, cg); break; case TOK_SEMI: @@ -6423,8 +6374,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * Don't eliminate apparently useless expressions if they are * labeled expression statements. The tc->topStmt->update test - * catches the case where we are nesting in js_EmitTree for a - * labeled compound statement. + * catches the case where we are nesting in EmitTree for a labeled + * compound statement. */ if (!useful && cg->topStmt && @@ -6468,9 +6419,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) pn2->pn_right->pn_funbox->joinable()) { pn2->pn_left->setOp(JSOP_SETMETHOD); } - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } } @@ -6491,24 +6442,22 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) pn2->expr()->isKind(TOK_LC))) ? SRC_LABELBRACE : SRC_LABEL; - noteIndex = js_NewSrcNote2(cx, cg, noteType, ptrdiff_t(index)); - if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { + noteIndex = NewSrcNote2(cx, cg, noteType, ptrdiff_t(index)); + if (noteIndex < 0 || Emit1(cx, cg, JSOP_NOP) < 0) return JS_FALSE; - } /* Emit code for the labeled statement. */ - js_PushStatement(cg, &stmtInfo, STMT_LABEL, CG_OFFSET(cg)); + PushStatement(cg, &stmtInfo, STMT_LABEL, CG_OFFSET(cg)); stmtInfo.label = atom; - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (!js_PopStatementCG(cx, cg)) + if (!PopStatementCG(cx, cg)) return JS_FALSE; /* If the statement was compound, emit a note for the end brace. */ if (noteType == SRC_LABELBRACE) { - if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || - js_Emit1(cx, cg, JSOP_NOP) < 0) { + if (NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 || + Emit1(cx, cg, JSOP_NOP) < 0) { return JS_FALSE; } } @@ -6522,19 +6471,19 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) */ off = noteIndex = -1; for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; tmp = CG_OFFSET(cg); if (noteIndex >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) return JS_FALSE; } if (!pn2->pn_next) break; off = tmp; - noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); + noteIndex = NewSrcNote2(cx, cg, SRC_PCDELTA, 0); if (noteIndex < 0 || - js_Emit1(cx, cg, JSOP_POP) < 0) { + Emit1(cx, cg, JSOP_POP) < 0) { return JS_FALSE; } } @@ -6547,13 +6496,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_HOOK: /* Emit the condition, then branch if false to the else part. */ - if (!js_EmitTree(cx, cg, pn->pn_kid1)) + if (!EmitTree(cx, cg, pn->pn_kid1)) return JS_FALSE; - noteIndex = js_NewSrcNote(cx, cg, SRC_COND); + noteIndex = NewSrcNote(cx, cg, SRC_COND); if (noteIndex < 0) return JS_FALSE; beq = EmitJump(cx, cg, JSOP_IFEQ, 0); - if (beq < 0 || !js_EmitTree(cx, cg, pn->pn_kid2)) + if (beq < 0 || !EmitTree(cx, cg, pn->pn_kid2)) return JS_FALSE; /* Jump around else, fixup the branch, emit else, fixup jump. */ @@ -6576,10 +6525,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) */ JS_ASSERT(cg->stackDepth > 0); cg->stackDepth--; - if (!js_EmitTree(cx, cg, pn->pn_kid3)) + if (!EmitTree(cx, cg, pn->pn_kid3)) return JS_FALSE; CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); - if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) + if (!SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq)) return JS_FALSE; break; @@ -6596,12 +6545,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * it pops and falls into the right operand's bytecode. */ if (pn->isArity(PN_BINARY)) { - if (!js_EmitTree(cx, cg, pn->pn_left)) + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0); if (top < 0) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; off = CG_OFFSET(cg); pc = CG_CODE(cg, top); @@ -6613,7 +6562,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Left-associative operator chain: avoid too much recursion. */ pn2 = pn->pn_head; - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0); if (top < 0) @@ -6622,7 +6571,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* Emit nodes between the head and the tail. */ jmp = top; while ((pn2 = pn2->pn_next)->pn_next) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; off = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0); if (off < 0) @@ -6632,7 +6581,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) jmp = off; } - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; pn2 = pn->pn_head; @@ -6662,13 +6611,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (pn->isArity(PN_LIST)) { /* Left-associative operator chain: avoid too much recursion. */ pn2 = pn->pn_head; - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; op = pn->getOp(); while ((pn2 = pn2->pn_next) != NULL) { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } } else { @@ -6677,7 +6626,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_DBLCOLON: if (pn->isArity(PN_NAME)) { - if (!js_EmitTree(cx, cg, pn->expr())) + if (!EmitTree(cx, cg, pn->expr())) return JS_FALSE; if (!EmitAtomOp(cx, pn, pn->getOp(), cg)) return JS_FALSE; @@ -6694,14 +6643,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) #endif /* Binary operators that evaluate both operands unconditionally. */ - if (!js_EmitTree(cx, cg, pn->pn_left)) + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; #if JS_HAS_XML_SUPPORT cg->flags |= oldflags & TCF_IN_FOR_INIT; #endif - if (js_Emit1(cx, cg, pn->getOp()) < 0) + if (Emit1(cx, cg, pn->getOp()) < 0) return JS_FALSE; } break; @@ -6733,10 +6682,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) oldflags = cg->flags; cg->flags &= ~TCF_IN_FOR_INIT; - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; cg->flags |= oldflags & TCF_IN_FOR_INIT; - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; break; } @@ -6755,7 +6704,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; op = pn2->getOp(); if (op == JSOP_CALLEE) { - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } else if (!pn2->pn_cookie.isFree()) { atomIndex = pn2->pn_cookie.asInteger(); @@ -6772,14 +6721,14 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) break; } if (pn2->isConst()) { - if (js_Emit1(cx, cg, JSOP_POS) < 0) + if (Emit1(cx, cg, JSOP_POS) < 0) return JS_FALSE; op = pn->getOp(); if (!(js_CodeSpec[op].format & JOF_POST)) { - if (js_Emit1(cx, cg, JSOP_ONE) < 0) + if (Emit1(cx, cg, JSOP_ONE) < 0) return JS_FALSE; op = (js_CodeSpec[op].format & JOF_INC) ? JSOP_ADD : JSOP_SUB; - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } } @@ -6793,13 +6742,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; break; case TOK_LP: - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, - CG_OFFSET(cg) - pn2->pn_offset) < 0) { + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - pn2->pn_offset) < 0) return JS_FALSE; - } - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; /* * This is dead code for the decompiler, don't generate @@ -6808,17 +6755,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) */ JS_ASSERT(js_CodeSpec[op].format & JOF_DECOMPOSE); JS_ASSERT(js_CodeSpec[op].format & JOF_ELEM); - if (js_Emit1(cx, cg, (JSOp)1) < 0) + if (Emit1(cx, cg, (JSOp)1) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_POP) < 0) + if (Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; break; #if JS_HAS_XML_SUPPORT case TOK_UNARYOP: JS_ASSERT(pn2->isOp(JSOP_SETXMLNAME)); - if (!js_EmitTree(cx, cg, pn2->pn_kid)) + if (!EmitTree(cx, cg, pn2->pn_kid)) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) + if (Emit1(cx, cg, JSOP_BINDXMLNAME) < 0) return JS_FALSE; if (!EmitElemIncDec(cx, NULL, op, cg)) return JS_FALSE; @@ -6839,7 +6786,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; op = pn2->getOp(); if (op == JSOP_FALSE) { - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } else { if (!EmitAtomOp(cx, pn2, op, cg)) @@ -6872,18 +6819,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) off = noteIndex = -1; } else { JS_ASSERT_IF(pn2->isKind(TOK_LP), !(pn2->pn_xflags & PNX_SETCALL)); - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; off = CG_OFFSET(cg); - noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0); - if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0) + noteIndex = NewSrcNote2(cx, cg, SRC_PCDELTA, 0); + if (noteIndex < 0 || Emit1(cx, cg, JSOP_POP) < 0) return JS_FALSE; } - if (js_Emit1(cx, cg, JSOP_TRUE) < 0) + if (Emit1(cx, cg, JSOP_TRUE) < 0) return JS_FALSE; if (noteIndex >= 0) { tmp = CG_OFFSET(cg); - if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) + if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off)) return JS_FALSE; } } @@ -6891,7 +6838,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) #if JS_HAS_XML_SUPPORT case TOK_FILTER: - if (!js_EmitTree(cx, cg, pn->pn_left)) + if (!EmitTree(cx, cg, pn->pn_left)) return JS_FALSE; jmp = EmitJump(cx, cg, JSOP_FILTER, 0); if (jmp < 0) @@ -6899,7 +6846,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) top = EmitTraceOp(cx, cg, pn->pn_right); if (top < 0) return JS_FALSE; - if (!js_EmitTree(cx, cg, pn->pn_right)) + if (!EmitTree(cx, cg, pn->pn_right)) return JS_FALSE; CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp); if (EmitJump(cx, cg, JSOP_ENDFILTER, top - CG_OFFSET(cg)) < 0) @@ -6979,12 +6926,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) #endif /* FALL THROUGH */ default: - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; callop = false; /* trigger JSOP_PUSH after */ break; } - if (!callop && js_Emit1(cx, cg, JSOP_PUSH) < 0) + if (!callop && Emit1(cx, cg, JSOP_PUSH) < 0) return JS_FALSE; /* Remember start of callable-object bytecode for decompilation hint. */ @@ -6998,15 +6945,15 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) uintN oldflags = cg->flags; cg->flags &= ~TCF_IN_FOR_INIT; for (pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) { - if (!js_EmitTree(cx, cg, pn3)) + if (!EmitTree(cx, cg, pn3)) return JS_FALSE; } cg->flags |= oldflags & TCF_IN_FOR_INIT; - if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0) + if (NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0) return JS_FALSE; argc = pn->pn_count - 1; - if (js_Emit3(cx, cg, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0) + if (Emit3(cx, cg, pn->getOp(), ARGC_HI(argc), ARGC_LO(argc)) < 0) return JS_FALSE; CheckTypeSet(cx, cg, pn->getOp()); if (pn->isOp(JSOP_EVAL)) { @@ -7015,7 +6962,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; } if (pn->pn_xflags & PNX_SETCALL) { - if (js_Emit1(cx, cg, JSOP_SETCALL) < 0) + if (Emit1(cx, cg, JSOP_SETCALL) < 0) return JS_FALSE; } break; @@ -7042,7 +6989,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * under the array initialiser code generator for array comprehension * special casing. */ - if (!js_EmitTree(cx, cg, pn->pn_kid)) + if (!EmitTree(cx, cg, pn->pn_kid)) return JS_FALSE; slot = AdjustBlockSlot(cx, cg, cg->arrayCompDepth); if (slot < 0) @@ -7084,7 +7031,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(cg->stackDepth > 0); saveDepth = cg->arrayCompDepth; cg->arrayCompDepth = (uint32) (cg->stackDepth - 1); - if (!js_EmitTree(cx, cg, pn->pn_head)) + if (!EmitTree(cx, cg, pn->pn_head)) return JS_FALSE; cg->arrayCompDepth = saveDepth; @@ -7107,7 +7054,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!EmitNewInit(cx, cg, JSProto_Array, pn, sharpnum)) return JS_FALSE; } else { - ptrdiff_t off = js_EmitN(cx, cg, JSOP_NEWARRAY, 3); + ptrdiff_t off = EmitN(cx, cg, JSOP_NEWARRAY, 3); if (off < 0) return JS_FALSE; pc = CG_CODE(cg, off); @@ -7119,20 +7066,20 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (!EmitNumberOp(cx, atomIndex, cg)) return JS_FALSE; if (pn2->isKind(TOK_COMMA) && pn2->isArity(PN_NULLARY)) { - if (js_Emit1(cx, cg, JSOP_HOLE) < 0) + if (Emit1(cx, cg, JSOP_HOLE) < 0) return JS_FALSE; } else { - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; } - if (js_Emit1(cx, cg, JSOP_INITELEM) < 0) + if (Emit1(cx, cg, JSOP_INITELEM) < 0) return JS_FALSE; } JS_ASSERT(atomIndex == pn->pn_count); if (pn->pn_xflags & PNX_ENDCOMMA) { /* Emit a source note so we know to decompile an extra comma. */ - if (js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0) + if (NewSrcNote(cx, cg, SRC_CONTINUE) < 0) return JS_FALSE; } @@ -7197,22 +7144,22 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) } /* Emit code for the property initializer. */ - if (!js_EmitTree(cx, cg, pn2->pn_right)) + if (!EmitTree(cx, cg, pn2->pn_right)) return JS_FALSE; op = pn2->getOp(); if (op == JSOP_GETTER || op == JSOP_SETTER) { obj = NULL; - if (js_Emit1(cx, cg, op) < 0) + if (Emit1(cx, cg, op) < 0) return JS_FALSE; } /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */ if (pn3->isKind(TOK_NUMBER)) { obj = NULL; - if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0) + if (NewSrcNote(cx, cg, SRC_INITPROP) < 0) return JS_FALSE; - if (js_Emit1(cx, cg, JSOP_INITELEM) < 0) + if (Emit1(cx, cg, JSOP_INITELEM) < 0) return JS_FALSE; } else { JS_ASSERT(pn3->isKind(TOK_NAME) || @@ -7222,7 +7169,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; /* Check whether we can optimize to JSOP_INITMETHOD. */ - JSParseNode *init = pn2->pn_right; + ParseNode *init = pn2->pn_right; bool lambda = init->isOp(JSOP_LAMBDA); if (lambda) ++methodInits; @@ -7259,7 +7206,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (cg->funbox && cg->funbox->shouldUnbrand(methodInits, slowMethodInits)) { obj = NULL; - if (js_Emit1(cx, cg, JSOP_UNBRAND) < 0) + if (Emit1(cx, cg, JSOP_UNBRAND) < 0) return JS_FALSE; } if (!EmitEndInit(cx, cg, pn->pn_count)) @@ -7270,7 +7217,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) * The object survived and has a predictable shape. Update the original bytecode, * as long as we can do so without using a big index prefix/suffix. */ - JSObjectBox *objbox = cg->parser->newObjectBox(obj); + ObjectBox *objbox = cg->parser->newObjectBox(obj); if (!objbox) return JS_FALSE; unsigned index = cg->objectList.index(objbox); @@ -7295,7 +7242,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) if (pn->isKind(TOK_RC)) goto do_emit_object; - if (!js_EmitTree(cx, cg, pn)) + if (!EmitTree(cx, cg, pn)) return JS_FALSE; EMIT_UINT16PAIR_IMM_OP(JSOP_DEFSHARP, cg->sharpSlotBase, (jsatomid) sharpnum); break; @@ -7310,7 +7257,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) /* * Cope with a left-over function definition that was replaced by a use * of a later function definition of the same name. See FunctionDef and - * MakeDefIntoUse in jsparse.cpp. + * MakeDefIntoUse in Parser.cpp. */ if (pn->isOp(JSOP_NOP)) break; @@ -7342,12 +7289,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_ANYNAME: #endif case TOK_PRIMARY: - if (js_Emit1(cx, cg, pn->getOp()) < 0) + if (Emit1(cx, cg, pn->getOp()) < 0) return JS_FALSE; break; case TOK_DEBUGGER: - if (js_Emit1(cx, cg, JSOP_DEBUGGER) < 0) + if (Emit1(cx, cg, JSOP_DEBUGGER) < 0) return JS_FALSE; break; @@ -7363,18 +7310,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) case TOK_XMLSTAGO: break; default: - if (js_Emit1(cx, cg, JSOP_STARTXML) < 0) + if (Emit1(cx, cg, JSOP_STARTXML) < 0) return JS_FALSE; } for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { if (pn2->isKind(TOK_LC) && - js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { + Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { return JS_FALSE; } - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0) + if (pn2 != pn->pn_head && Emit1(cx, cg, JSOP_ADD) < 0) return JS_FALSE; } @@ -7387,7 +7334,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return JS_FALSE; EMIT_INDEX_OP(JSOP_STRING, index); } - if (js_Emit1(cx, cg, pn->getOp()) < 0) + if (Emit1(cx, cg, pn->getOp()) < 0) return JS_FALSE; } #ifdef DEBUG @@ -7408,12 +7355,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) JS_ASSERT(pn->pn_count != 0); for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { if (pn2->isKind(TOK_LC) && - js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { + Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) { return JS_FALSE; } - if (!js_EmitTree(cx, cg, pn2)) + if (!EmitTree(cx, cg, pn2)) return JS_FALSE; - if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0) + if (pn2 != pn->pn_head && Emit1(cx, cg, JSOP_ADD) < 0) return JS_FALSE; } } else { @@ -7445,40 +7392,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) return ok; } -/* - * We should try to get rid of offsetBias (always 0 or 1, where 1 is - * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL. - */ -JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = { - {"null", 0, 0, 0}, - {"if", 0, 0, 0}, - {"if-else", 2, 0, 1}, - {"for", 3, 1, 1}, - {"while", 1, 0, 1}, - {"continue", 0, 0, 0}, - {"decl", 1, 1, 1}, - {"pcdelta", 1, 0, 1}, - {"assignop", 0, 0, 0}, - {"cond", 1, 0, 1}, - {"brace", 1, 0, 1}, - {"hidden", 0, 0, 0}, - {"pcbase", 1, 0, -1}, - {"label", 1, 0, 0}, - {"labelbrace", 1, 0, 0}, - {"endbrace", 0, 0, 0}, - {"break2label", 1, 0, 0}, - {"cont2label", 1, 0, 0}, - {"switch", 2, 0, 1}, - {"funcdef", 1, 0, 0}, - {"catch", 1, 0, 1}, - {"extended", -1, 0, 0}, - {"newline", 0, 0, 0}, - {"setline", 1, 0, 0}, - {"xdelta", 0, 0, 0}, -}; - static intN -AllocSrcNote(JSContext *cx, JSCodeGenerator *cg) +AllocSrcNote(JSContext *cx, CodeGenerator *cg) { jssrcnote *notes = CG_NOTES(cg); jssrcnote *newnotes; @@ -7509,7 +7424,7 @@ AllocSrcNote(JSContext *cx, JSCodeGenerator *cg) } intN -js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type) +NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type) { intN index, n; jssrcnote *sn; @@ -7546,48 +7461,47 @@ js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type) /* * Initialize type and delta, then allocate the minimum number of notes * needed for type's arity. Usually, we won't need more, but if an offset - * does take two bytes, js_SetSrcNoteOffset will grow CG_NOTES(cg). + * does take two bytes, SetSrcNoteOffset will grow CG_NOTES(cg). */ SN_MAKE_NOTE(sn, type, delta); for (n = (intN)js_SrcNoteSpec[type].arity; n > 0; n--) { - if (js_NewSrcNote(cx, cg, SRC_NULL) < 0) + if (NewSrcNote(cx, cg, SRC_NULL) < 0) return -1; } return index; } intN -js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset) +NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset) { intN index; - index = js_NewSrcNote(cx, cg, type); + index = NewSrcNote(cx, cg, type); if (index >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset)) + if (!SetSrcNoteOffset(cx, cg, index, 0, offset)) return -1; } return index; } intN -js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset1, ptrdiff_t offset2) +NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1, + ptrdiff_t offset2) { intN index; - index = js_NewSrcNote(cx, cg, type); + index = NewSrcNote(cx, cg, type); if (index >= 0) { - if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset1)) + if (!SetSrcNoteOffset(cx, cg, index, 0, offset1)) return -1; - if (!js_SetSrcNoteOffset(cx, cg, index, 1, offset2)) + if (!SetSrcNoteOffset(cx, cg, index, 1, offset2)) return -1; } return index; } static JSBool -GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg) +GrowSrcNotes(JSContext *cx, CodeGenerator *cg) { size_t newlength = CG_NOTE_LIMIT(cg) * 2; jssrcnote *newnotes = (jssrcnote *) cx->realloc_(CG_NOTES(cg), newlength); @@ -7601,14 +7515,13 @@ GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg) } jssrcnote * -js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, - ptrdiff_t delta) +AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta) { ptrdiff_t base, limit, newdelta, diff; intN index; /* - * Called only from OptimizeSpanDeps and js_FinishTakingSrcNotes to add to + * Called only from OptimizeSpanDeps and FinishTakingSrcNotes to add to * main script note deltas, and only by a small positive amount. */ JS_ASSERT(cg->current == &cg->main); @@ -7635,41 +7548,8 @@ js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, return sn; } -JS_FRIEND_API(uintN) -js_SrcNoteLength(jssrcnote *sn) -{ - uintN arity; - jssrcnote *base; - - arity = (intN)js_SrcNoteSpec[SN_TYPE(sn)].arity; - for (base = sn++; arity; sn++, arity--) { - if (*sn & SN_3BYTE_OFFSET_FLAG) - sn += 2; - } - return sn - base; -} - -JS_FRIEND_API(ptrdiff_t) -js_GetSrcNoteOffset(jssrcnote *sn, uintN which) -{ - /* Find the offset numbered which (i.e., skip exactly which offsets). */ - JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); - JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity); - for (sn++; which; sn++, which--) { - if (*sn & SN_3BYTE_OFFSET_FLAG) - sn += 2; - } - if (*sn & SN_3BYTE_OFFSET_FLAG) { - return (ptrdiff_t)(((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK) << 16) - | (sn[1] << 8) - | sn[2]); - } - return (ptrdiff_t)*sn; -} - JSBool -js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, - uintN which, ptrdiff_t offset) +SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset) { jssrcnote *sn; ptrdiff_t diff; @@ -7727,7 +7607,7 @@ js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, #define NBINS 10 static uint32 hist[NBINS]; -void DumpSrcNoteSizeHist() +static void DumpSrcNoteSizeHist() { static FILE *fp; int i, n; @@ -7751,12 +7631,13 @@ void DumpSrcNoteSizeHist() /* * Fill in the storage at notes with prolog and main srcnotes; the space at - * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from jsemit.h. - * SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST CHECKING WHETHER jsemit.h's - * CG_COUNT_FINAL_SRCNOTES MACRO NEEDS CORRESPONDING CHANGES! + * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from + * BytecodeGenerator.h. SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST + * CHECKING WHETHER BytecodeGenerator.h's CG_COUNT_FINAL_SRCNOTES MACRO NEEDS + * CORRESPONDING CHANGES! */ JSBool -js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes) +FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes) { uintN prologCount, mainCount, totalCount; ptrdiff_t offset, delta; @@ -7767,8 +7648,8 @@ js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes) prologCount = cg->prolog.noteCount; if (prologCount && cg->prolog.currentLine != cg->firstLine) { CG_SWITCH_TO_PROLOG(cg); - if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)cg->firstLine) < 0) - return JS_FALSE; + if (NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)cg->firstLine) < 0) + return false; prologCount = cg->prolog.noteCount; CG_SWITCH_TO_MAIN(cg); } else { @@ -7790,8 +7671,8 @@ js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes) if (offset < delta) delta = offset; for (;;) { - if (!js_AddToSrcNoteDelta(cx, cg, sn, delta)) - return JS_FALSE; + if (!AddToSrcNoteDelta(cx, cg, sn, delta)) + return false; offset -= delta; if (offset == 0) break; @@ -7808,19 +7689,19 @@ js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes) memcpy(notes + prologCount, cg->main.notes, SRCNOTE_SIZE(mainCount)); SN_MAKE_TERMINATOR(¬es[totalCount]); - return JS_TRUE; + return true; } static JSBool -NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind, - uintN stackDepth, size_t start, size_t end) +NewTryNote(JSContext *cx, CodeGenerator *cg, JSTryNoteKind kind, uintN stackDepth, size_t start, + size_t end) { JS_ASSERT((uintN)(uint16)stackDepth == stackDepth); JS_ASSERT(start <= end); JS_ASSERT((size_t)(uint32)start == start); JS_ASSERT((size_t)(uint32)end == end); - JSTryNode *tryNode = cx->tempLifoAlloc().new_(); + TryNode *tryNode = cx->tempLifoAlloc().new_(); if (!tryNode) { js_ReportOutOfMemory(cx); return JS_FALSE; @@ -7837,9 +7718,9 @@ NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind, } void -js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array) +FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array) { - JSTryNode *tryNode; + TryNode *tryNode; JSTryNote *tn; JS_ASSERT(array->length > 0 && array->length == cg->ntrynotes); @@ -7851,21 +7732,23 @@ js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array) JS_ASSERT(tn == array->vector); } +} /* namespace frontend */ + /* * Find the index of the given object for code generator. * * Since the emitter refers to each parsed object only once, for the index we * use the number of already indexes objects. We also add the object to a list * to convert the list to a fixed-size array when we complete code generation, - * see JSCGObjectList::finish below. + * see js::CGObjectList::finish below. * - * Most of the objects go to JSCodeGenerator.objectList but for regexp we use a - * separated JSCodeGenerator.regexpList. In this way the emitted index can be + * Most of the objects go to CodeGenerator::objectList but for regexp we use a + * separated CodeGenerator::regexpList. In this way the emitted index can be * directly used to store and fetch a reference to a cloned RegExp object that * shares the same JSRegExp private data created for the object literal in - * objbox. We need a cloned object to hold lastIndex and other direct properties - * that should not be shared among threads sharing a precompiled function or - * script. + * objbox. We need a cloned object to hold lastIndex and other direct + * properties that should not be shared among threads sharing a precompiled + * function or script. * * If the code being compiled is function code, allocate a reserved slot in * the cloned function object that shares its precompiled script with other @@ -7894,7 +7777,7 @@ js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array) * the pre-compilation prototype, a pigeon-hole problem for instanceof tests. */ uintN -JSCGObjectList::index(JSObjectBox *objbox) +CGObjectList::index(ObjectBox *objbox) { JS_ASSERT(!objbox->emitLink); objbox->emitLink = lastbox; @@ -7904,16 +7787,13 @@ JSCGObjectList::index(JSObjectBox *objbox) } void -JSCGObjectList::finish(JSObjectArray *array) +CGObjectList::finish(JSObjectArray *array) { - JSObject **cursor; - JSObjectBox *objbox; - JS_ASSERT(length <= INDEX_LIMIT); JS_ASSERT(length == array->length); - cursor = array->vector + array->length; - objbox = lastbox; + JSObject **cursor = array->vector + array->length; + ObjectBox *objbox = lastbox; do { --cursor; JS_ASSERT(!*cursor); @@ -7923,7 +7803,7 @@ JSCGObjectList::finish(JSObjectArray *array) } void -JSGCConstList::finish(JSConstArray *array) +GCConstList::finish(JSConstArray *array) { JS_ASSERT(array->length == list.length()); Value *src = list.begin(), *srcend = list.end(); @@ -7931,3 +7811,69 @@ JSGCConstList::finish(JSConstArray *array) for (; src != srcend; ++src, ++dst) *dst = *src; } + +} /* namespace js */ + +/* + * We should try to get rid of offsetBias (always 0 or 1, where 1 is + * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL. + */ +JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = { + {"null", 0, 0, 0}, + {"if", 0, 0, 0}, + {"if-else", 2, 0, 1}, + {"for", 3, 1, 1}, + {"while", 1, 0, 1}, + {"continue", 0, 0, 0}, + {"decl", 1, 1, 1}, + {"pcdelta", 1, 0, 1}, + {"assignop", 0, 0, 0}, + {"cond", 1, 0, 1}, + {"brace", 1, 0, 1}, + {"hidden", 0, 0, 0}, + {"pcbase", 1, 0, -1}, + {"label", 1, 0, 0}, + {"labelbrace", 1, 0, 0}, + {"endbrace", 0, 0, 0}, + {"break2label", 1, 0, 0}, + {"cont2label", 1, 0, 0}, + {"switch", 2, 0, 1}, + {"funcdef", 1, 0, 0}, + {"catch", 1, 0, 1}, + {"extended", -1, 0, 0}, + {"newline", 0, 0, 0}, + {"setline", 1, 0, 0}, + {"xdelta", 0, 0, 0}, +}; + +JS_FRIEND_API(uintN) +js_SrcNoteLength(jssrcnote *sn) +{ + uintN arity; + jssrcnote *base; + + arity = (intN)js_SrcNoteSpec[SN_TYPE(sn)].arity; + for (base = sn++; arity; sn++, arity--) { + if (*sn & SN_3BYTE_OFFSET_FLAG) + sn += 2; + } + return sn - base; +} + +JS_FRIEND_API(ptrdiff_t) +js_GetSrcNoteOffset(jssrcnote *sn, uintN which) +{ + /* Find the offset numbered which (i.e., skip exactly which offsets). */ + JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA); + JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity); + for (sn++; which; sn++, which--) { + if (*sn & SN_3BYTE_OFFSET_FLAG) + sn += 2; + } + if (*sn & SN_3BYTE_OFFSET_FLAG) { + return (ptrdiff_t)(((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK) << 16) + | (sn[1] << 8) + | sn[2]); + } + return (ptrdiff_t)*sn; +} diff --git a/js/src/frontend/BytecodeGenerator.h b/js/src/frontend/BytecodeGenerator.h index a4b51c58001f..a8bb00c6ce30 100644 --- a/js/src/frontend/BytecodeGenerator.h +++ b/js/src/frontend/BytecodeGenerator.h @@ -56,7 +56,7 @@ #include "jsatominlines.h" -JS_BEGIN_EXTERN_C +namespace js { /* * NB: If you add enumerators for scope statements, add them between STMT_WITH @@ -64,9 +64,10 @@ JS_BEGIN_EXTERN_C * non-looping statement enumerators, add them before STMT_DO_LOOP or you will * break the STMT_TYPE_IS_LOOP macro. * - * Also remember to keep the statementName array in jsemit.c in sync. + * Also remember to keep the statementName array in BytecodeGenerator.cpp in + * sync. */ -typedef enum JSStmtType { +enum StmtType { STMT_LABEL, /* labeled statement: L: s */ STMT_IF, /* if (then) statement */ STMT_ELSE, /* else clause of if statement */ @@ -83,12 +84,12 @@ typedef enum JSStmtType { STMT_FOR_IN_LOOP, /* for/in loop statement */ STMT_WHILE_LOOP, /* while loop statement */ STMT_LIMIT -} JSStmtType; +}; #define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b))) /* - * A comment on the encoding of the JSStmtType enum and type-testing macros: + * A comment on the encoding of the js::StmtType enum and type-testing macros: * * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may * become, a lexical scope. It therefore includes block and switch (the two @@ -96,7 +97,7 @@ typedef enum JSStmtType { * pending the "reformed with" in ES4/JS2). It includes all try-catch-finally * types, which are high-numbered maybe-scope types. * - * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly + * STMT_TYPE_LINKS_SCOPE tells whether a js::StmtInfo of the given type eagerly * links to other scoping statement info records. It excludes the two early * "maybe" types, block and switch, as well as the try and both finally types, * since try and the other trailing maybe-scope types don't need block scope @@ -124,9 +125,7 @@ typedef enum JSStmtType { #define STMT_IS_TRYING(stmt) STMT_TYPE_IS_TRYING((stmt)->type) #define STMT_IS_LOOP(stmt) STMT_TYPE_IS_LOOP((stmt)->type) -typedef struct JSStmtInfo JSStmtInfo; - -struct JSStmtInfo { +struct StmtInfo { uint16 type; /* statement type */ uint16 flags; /* flags, see below */ uint32 blockid; /* for simplified dominance computation */ @@ -135,10 +134,10 @@ struct JSStmtInfo { ptrdiff_t continues; /* offset of last continue in loop */ union { JSAtom *label; /* name of LABEL */ - JSObjectBox *blockBox; /* block scope object */ + ObjectBox *blockBox; /* block scope object */ }; - JSStmtInfo *down; /* info for enclosing statement */ - JSStmtInfo *downScope; /* next enclosing lexical scope */ + StmtInfo *down; /* info for enclosing statement */ + StmtInfo *downScope; /* next enclosing lexical scope */ }; #define SIF_SCOPE 0x0001 /* statement has its own lexical scope */ @@ -146,12 +145,12 @@ struct JSStmtInfo { #define SIF_FOR_BLOCK 0x0004 /* for (let ...) induced block scope */ /* - * To reuse space in JSStmtInfo, rename breaks and continues for use during + * To reuse space in StmtInfo, rename breaks and continues for use during * try/catch/finally code generation and backpatching. To match most common * use cases, the macro argument is a struct, not a struct pointer. Only a * loop, switch, or label statement info record can have breaks and continues, * and only a for loop has an update backpatch chain, so it's safe to overlay - * these for the "trying" JSStmtTypes. + * these for the "trying" StmtTypes. */ #define CATCHNOTE(stmt) ((stmt).update) #define GOSUBS(stmt) ((stmt).breaks) @@ -160,7 +159,7 @@ struct JSStmtInfo { #define SET_STATEMENT_TOP(stmt, top) \ ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1)) -#define TCF_COMPILING 0x01 /* JSTreeContext is JSCodeGenerator */ +#define TCF_COMPILING 0x01 /* TreeContext is CodeGenerator */ #define TCF_IN_FUNCTION 0x02 /* parsing inside function body */ #define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */ #define TCF_RETURN_VOID 0x08 /* function has 'return;' */ @@ -196,10 +195,10 @@ struct JSStmtInfo { #define TCF_DECL_DESTRUCTURING 0x10000 /* - * A request flag passed to Compiler::compileScript and then down via - * JSCodeGenerator to js_NewScriptFromCG, from script_compile_sub and any - * kindred functions that need to make mutable scripts (even empty ones; - * i.e., they can't share the const JSScript::emptyScript() singleton). + * A request flag passed to BytecodeCompiler::compileScript and then down via + * CodeGenerator to JSScript::NewScriptFromCG, from script_compile_sub and any + * kindred functions that need to make mutable scripts (even empty ones; i.e., + * they can't share the const JSScript::emptyScript() singleton). */ #define TCF_NEED_MUTABLE_SCRIPT 0x20000 @@ -299,7 +298,9 @@ struct JSStmtInfo { TCF_STRICT_MODE_CODE | \ TCF_FUN_EXTENSIBLE_SCOPE) -struct JSTreeContext { /* tree context for semantic checks */ +struct CodeGenerator; + +struct TreeContext { /* tree context for semantic checks */ uint32 flags; /* statement state flags, see above */ uint32 bodyid; /* block number of program/function body */ uint32 blockidGen; /* preincremented block number generator */ @@ -309,19 +310,19 @@ struct JSTreeContext { /* tree context for semantic checks */ non-zero depth in current paren tree */ uint32 argumentsCount; /* number of |arguments| references encountered at non-zero depth in current paren tree */ - JSStmtInfo *topStmt; /* top of statement info stack */ - JSStmtInfo *topScopeStmt; /* top lexical scope statement */ - JSObjectBox *blockChainBox; /* compile time block scope chain (NB: one + StmtInfo *topStmt; /* top of statement info stack */ + StmtInfo *topScopeStmt; /* top lexical scope statement */ + ObjectBox *blockChainBox; /* compile time block scope chain (NB: one deeper than the topScopeStmt/downScope chain when in head of let block/expr) */ - JSParseNode *blockNode; /* parse node for a block with let declarations + ParseNode *blockNode; /* parse node for a block with let declarations (block with its own lexical scope) */ - js::AtomDecls decls; /* function, const, and var declarations */ - js::Parser *parser; /* ptr to common parsing and lexing data */ - JSParseNode *yieldNode; /* parse node for a yield expression that might + AtomDecls decls; /* function, const, and var declarations */ + Parser *parser; /* ptr to common parsing and lexing data */ + ParseNode *yieldNode; /* parse node for a yield expression that might be an error if we turn out to be inside a generator expression */ - JSParseNode *argumentsNode; /* parse node for an arguments variable that + ParseNode *argumentsNode; /* parse node for an arguments variable that might be an error if we turn out to be inside a generator expression */ @@ -350,23 +351,23 @@ struct JSTreeContext { /* tree context for semantic checks */ scopeChain_ = scopeChain; } - js::OwnedAtomDefnMapPtr lexdeps;/* unresolved lexical name dependencies */ - JSTreeContext *parent; /* enclosing function or global context */ + OwnedAtomDefnMapPtr lexdeps; /* unresolved lexical name dependencies */ + TreeContext *parent; /* enclosing function or global context */ uintN staticLevel; /* static compilation unit nesting level */ - JSFunctionBox *funbox; /* null or box for function we're compiling + FunctionBox *funbox; /* null or box for function we're compiling if (flags & TCF_IN_FUNCTION) and not in - Compiler::compileFunctionBody */ - JSFunctionBox *functionList; + BytecodeCompiler::compileFunctionBody */ + FunctionBox *functionList; - JSParseNode *innermostWith; /* innermost WITH parse node */ + ParseNode *innermostWith; /* innermost WITH parse node */ - js::Bindings bindings; /* bindings in this code, including + Bindings bindings; /* bindings in this code, including arguments if we're compiling a function */ void trace(JSTracer *trc); - JSTreeContext(js::Parser *prs) + TreeContext(Parser *prs) : flags(0), bodyid(0), blockidGen(0), parenDepth(0), yieldCount(0), argumentsCount(0), topStmt(NULL), topScopeStmt(NULL), blockChainBox(NULL), blockNode(NULL), decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL), scopeChain_(NULL), @@ -381,14 +382,14 @@ struct JSTreeContext { /* tree context for semantic checks */ * time during code generation. To avoid a redundant stats update in such * cases, we store uint16(-1) in maxScopeDepth. */ - ~JSTreeContext() { + ~TreeContext() { parser->tc = this->parent; } /* - * JSCodeGenerator derives from JSTreeContext; however, only the top-level - * JSCodeGenerators are actually used as full-fledged tree contexts (to - * hold decls and lexdeps). We can avoid allocation overhead by making + * js::CodeGenerator derives from js::TreeContext; however, only the + * top-level CodeGenerators are actually used as full-fledged tree contexts + * (to hold decls and lexdeps). We can avoid allocation overhead by making * this distinction explicit. */ enum InitBehavior { @@ -419,7 +420,7 @@ struct JSTreeContext { /* tree context for semantic checks */ bool atBodyLevel() { return !topStmt || (topStmt->flags & SIF_BODY_BLOCK); } /* Test whether we're in a statement of given type. */ - bool inStatement(JSStmtType type); + bool inStatement(StmtType type); bool inStrictMode() const { return flags & TCF_STRICT_MODE_CODE; @@ -434,7 +435,7 @@ struct JSTreeContext { /* tree context for semantic checks */ int sharpSlotBase; bool ensureSharpSlots(); - js::Compiler *compiler() { return (js::Compiler *)parser; } + BytecodeCompiler *compiler() { return (BytecodeCompiler *) parser; } // Return true there is a generator function within |skip| lexical scopes // (going upward) from this context's lexical scope. Always return true if @@ -445,7 +446,7 @@ struct JSTreeContext { /* tree context for semantic checks */ bool inFunction() const { return flags & TCF_IN_FUNCTION; } bool compiling() const { return flags & TCF_COMPILING; } - inline JSCodeGenerator *asCodeGenerator(); + inline CodeGenerator *asCodeGenerator(); bool usesArguments() const { return flags & TCF_FUN_USES_ARGUMENTS; @@ -477,7 +478,7 @@ struct JSTreeContext { /* tree context for semantic checks */ return flags & TCF_FUN_MUTATES_PARAMETER; } - void noteArgumentsUse(JSParseNode *pn) { + void noteArgumentsUse(ParseNode *pn) { JS_ASSERT(inFunction()); countArgumentsUse(pn); flags |= TCF_FUN_USES_ARGUMENTS; @@ -485,7 +486,7 @@ struct JSTreeContext { /* tree context for semantic checks */ funbox->node->pn_dflags |= PND_FUNARG; } - void countArgumentsUse(JSParseNode *pn) { + void countArgumentsUse(ParseNode *pn) { JS_ASSERT(pn->pn_atom == parser->context->runtime->atomState.argumentsAtom); argumentsCount++; argumentsNode = pn; @@ -502,38 +503,39 @@ struct JSTreeContext { /* tree context for semantic checks */ bool hasExtensibleScope() const { return flags & TCF_FUN_EXTENSIBLE_SCOPE; } + + ParseNode *freeTree(ParseNode *pn) { return parser->freeTree(pn); } }; /* * Return true if we need to check for conditions that elicit * JSOPTION_STRICT warnings or strict mode errors. */ -inline bool JSTreeContext::needStrictChecks() { +inline bool TreeContext::needStrictChecks() { return parser->context->hasStrictOption() || inStrictMode(); } -namespace js { +namespace frontend { bool -SetStaticLevel(JSTreeContext *tc, uintN staticLevel); +SetStaticLevel(TreeContext *tc, uintN staticLevel); bool -GenerateBlockId(JSTreeContext *tc, uint32& blockid); +GenerateBlockId(TreeContext *tc, uint32& blockid); -} /* namespace js */ +} /* namespace frontend */ + +struct JumpTarget; /* * Span-dependent instructions are jumps whose span (from the jump bytecode to * the jump target) may require 2 or 4 bytes of immediate operand. */ -typedef struct JSSpanDep JSSpanDep; -typedef struct JSJumpTarget JSJumpTarget; - -struct JSSpanDep { +struct SpanDep { ptrdiff_t top; /* offset of first bytecode in an opcode */ ptrdiff_t offset; /* offset - 1 within opcode of jump operand */ ptrdiff_t before; /* original offset - 1 of jump operand */ - JSJumpTarget *target; /* tagged target pointer or backpatch delta */ + JumpTarget *target; /* tagged target pointer or backpatch delta */ }; /* @@ -542,10 +544,10 @@ struct JSSpanDep { * instruction whose jump offset operand must be extended can be found quickly * and adjusted upward (toward higher offsets). */ -struct JSJumpTarget { +struct JumpTarget { ptrdiff_t offset; /* offset of span-dependent jump target */ int balance; /* AVL tree balance number */ - JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */ + JumpTarget *kids[2]; /* left and right AVL tree child pointers */ }; #define JT_LEFT 0 @@ -555,20 +557,20 @@ struct JSJumpTarget { #define JT_DIR(imbalance) (((imbalance) + 1) >> 1) /* - * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear, + * Backpatch deltas are encoded in js::SpanDep::target if JT_TAG_BIT is clear, * so we can maintain backpatch chains when using span dependency records to * hold jump offsets that overflow 16 bits. */ #define JT_TAG_BIT ((jsword) 1) #define JT_UNTAG_SHIFT 1 -#define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT)) -#define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT)) +#define JT_SET_TAG(jt) ((JumpTarget *)((jsword)(jt) | JT_TAG_BIT)) +#define JT_CLR_TAG(jt) ((JumpTarget *)((jsword)(jt) & ~JT_TAG_BIT)) #define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT) #define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE) #define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT) #define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1) -#define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT)) +#define BPDELTA_TO_JT(bp) ((JumpTarget *)((bp) << JT_UNTAG_SHIFT)) #define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT)) #define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt)) @@ -583,34 +585,31 @@ struct JSJumpTarget { ? JT_CLR_TAG((sd)->target)->offset - (pivot) \ : 0) -typedef struct JSTryNode JSTryNode; - -struct JSTryNode { +struct TryNode { JSTryNote note; - JSTryNode *prev; + TryNode *prev; }; -struct JSCGObjectList { +struct CGObjectList { uint32 length; /* number of emitted so far objects */ - JSObjectBox *lastbox; /* last emitted object */ + ObjectBox *lastbox; /* last emitted object */ - JSCGObjectList() : length(0), lastbox(NULL) {} + CGObjectList() : length(0), lastbox(NULL) {} - uintN index(JSObjectBox *objbox); + uintN index(ObjectBox *objbox); void finish(JSObjectArray *array); }; -class JSGCConstList { - js::Vector list; +class GCConstList { + Vector list; public: - JSGCConstList(JSContext *cx) : list(cx) {} - bool append(js::Value v) { return list.append(v); } + GCConstList(JSContext *cx) : list(cx) {} + bool append(Value v) { return list.append(v); } size_t length() const { return list.length(); } void finish(JSConstArray *array); - }; -struct JSCodeGenerator : public JSTreeContext +struct CodeGenerator : public TreeContext { struct { jsbytecode *base; /* base of JS bytecode vector */ @@ -623,19 +622,19 @@ struct JSCodeGenerator : public JSTreeContext uintN currentLine; /* line number for tree-based srcnote gen */ } prolog, main, *current; - js::OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */ - js::AtomDefnMapPtr roLexdeps; - uintN firstLine; /* first line, for js_NewScriptFromCG */ + OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */ + AtomDefnMapPtr roLexdeps; + uintN firstLine; /* first line, for JSScript::NewScriptFromCG */ intN stackDepth; /* current stack depth in script frame */ uintN maxStackDepth; /* maximum stack depth so far */ uintN ntrynotes; /* number of allocated so far try notes */ - JSTryNode *lastTryNode; /* the last allocated try node */ + TryNode *lastTryNode; /* the last allocated try node */ - JSSpanDep *spanDeps; /* span dependent instruction records */ - JSJumpTarget *jumpTargets; /* AVL tree of jump target offsets */ - JSJumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */ + SpanDep *spanDeps; /* span dependent instruction records */ + JumpTarget *jumpTargets; /* AVL tree of jump target offsets */ + JumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */ uintN numSpanDeps; /* number of span dependencies */ uintN numJumpTargets; /* number of jump targets */ ptrdiff_t spanDepTodo; /* offset from main.base of potentially @@ -643,36 +642,36 @@ struct JSCodeGenerator : public JSTreeContext uintN arrayCompDepth; /* stack depth of array in comprehension */ - uintN emitLevel; /* js_EmitTree recursion level */ + uintN emitLevel; /* js::frontend::EmitTree recursion level */ - typedef js::HashMap ConstMap; + typedef HashMap ConstMap; ConstMap constMap; /* compile time constants */ - JSGCConstList constList; /* constants to be included with the script */ + GCConstList constList; /* constants to be included with the script */ - JSCGObjectList objectList; /* list of emitted objects */ - JSCGObjectList regexpList; /* list of emitted regexp that will be + CGObjectList objectList; /* list of emitted objects */ + CGObjectList regexpList; /* list of emitted regexp that will be cloned during execution */ - js::OwnedAtomIndexMapPtr upvarIndices; /* map of atoms to upvar indexes */ + OwnedAtomIndexMapPtr upvarIndices; /* map of atoms to upvar indexes */ - js::UpvarCookies upvarMap; /* indexed upvar slot locations */ + UpvarCookies upvarMap; /* indexed upvar slot locations */ - typedef js::Vector GlobalUseVector; + typedef Vector GlobalUseVector; GlobalUseVector globalUses; /* per-script global uses */ - js::OwnedAtomIndexMapPtr globalMap; /* per-script map of global name to globalUses vector */ + OwnedAtomIndexMapPtr globalMap; /* per-script map of global name to globalUses vector */ /* Vectors of pn_cookie slot values. */ - typedef js::Vector SlotVector; + typedef Vector SlotVector; SlotVector closedArgs; SlotVector closedVars; uint16 traceIndex; /* index for the next JSOP_TRACE instruction */ uint16 typesetCount; /* Number of JOF_TYPESET opcodes generated */ - JSCodeGenerator(js::Parser *parser, uintN lineno); - bool init(JSContext *cx, JSTreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR); + CodeGenerator(Parser *parser, uintN lineno); + bool init(JSContext *cx, TreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR); JSContext *context() { return parser->context; @@ -681,9 +680,9 @@ struct JSCodeGenerator : public JSTreeContext /* * Note that cgs are magic: they own the arena "top-of-stack" space above * their tempMark points. This means that you cannot alloc from tempPool - * and save the pointer beyond the next JSCodeGenerator destructor call. + * and save the pointer beyond the next CodeGenerator destructor call. */ - ~JSCodeGenerator(); + ~CodeGenerator(); /* * Adds a use of a variable that is statically known to exist on the @@ -699,7 +698,7 @@ struct JSCodeGenerator : public JSTreeContext * If the global use can be cached, |cookie| will be set to |slot|. * Otherwise, |cookie| is set to the free cookie value. */ - bool addGlobalUse(JSAtom *atom, uint32 slot, js::UpvarCookie *cookie); + bool addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie); bool hasUpvarIndices() const { return upvarIndices.hasMap() && !upvarIndices->empty(); @@ -718,11 +717,11 @@ struct JSCodeGenerator : public JSTreeContext bool compilingForEval() const { return !!(flags & TCF_COMPILE_FOR_EVAL); } JSVersion version() const { return parser->versionWithFlags(); } - bool shouldNoteClosedName(JSParseNode *pn); + bool shouldNoteClosedName(ParseNode *pn); JS_ALWAYS_INLINE bool makeAtomIndex(JSAtom *atom, jsatomid *indexp) { - js::AtomIndexAddPtr p = atomIndices->lookupForAdd(atom); + AtomIndexAddPtr p = atomIndices->lookupForAdd(atom); if (p) { *indexp = p.value(); return true; @@ -739,7 +738,7 @@ struct JSCodeGenerator : public JSTreeContext bool checkSingletonContext() { if (!compileAndGo() || inFunction()) return false; - for (JSStmtInfo *stmt = topStmt; stmt; stmt = stmt->down) { + for (StmtInfo *stmt = topStmt; stmt; stmt = stmt->down) { if (STMT_IS_LOOP(stmt)) return false; } @@ -771,51 +770,53 @@ struct JSCodeGenerator : public JSTreeContext #define CG_SWITCH_TO_MAIN(cg) ((cg)->current = &(cg)->main) #define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog) -inline JSCodeGenerator * -JSTreeContext::asCodeGenerator() +inline CodeGenerator * +TreeContext::asCodeGenerator() { JS_ASSERT(compiling()); - return static_cast(this); + return static_cast(this); } +namespace frontend { + /* * Emit one bytecode. */ -extern ptrdiff_t -js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op); +ptrdiff_t +Emit1(JSContext *cx, CodeGenerator *cg, JSOp op); /* * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1). */ -extern ptrdiff_t -js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1); +ptrdiff_t +Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1); /* * Emit three bytecodes, an opcode with two bytes of immediate operands. */ -extern ptrdiff_t -js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1, +ptrdiff_t +Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1, jsbytecode op2); /* * Emit five bytecodes, an opcode with two 16-bit immediates. */ -extern ptrdiff_t -js_Emit5(JSContext *cx, JSCodeGenerator *cg, JSOp op, uint16 op1, +ptrdiff_t +Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2); /* * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand. */ -extern ptrdiff_t -js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra); +ptrdiff_t +EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra); /* - * Unsafe macro to call js_SetJumpOffset and return false if it does. + * Unsafe macro to call SetJumpOffset and return false if it does. */ #define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,BAD_EXIT) \ JS_BEGIN_MACRO \ - if (!js_SetJumpOffset(cx, cg, pc, off)) { \ + if (!SetJumpOffset(cx, cg, pc, off)) { \ BAD_EXIT; \ } \ JS_END_MACRO @@ -830,56 +831,52 @@ js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra); #define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \ CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, off, return JS_FALSE) -extern JSBool -js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, - ptrdiff_t off); +JSBool +SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off); /* * Push the C-stack-allocated struct at stmt onto the stmtInfo stack. */ -extern void -js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type, - ptrdiff_t top); +void +PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top); /* * Push a block scope statement and link blockObj into tc->blockChain. To pop - * this statement info record, use js_PopStatement as usual, or if appropriate - * (if generating code), js_PopStatementCG. + * this statement info record, use PopStatementTC as usual, or if appropriate + * (if generating code), PopStatementCG. */ -extern void -js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObjectBox *blockBox, - ptrdiff_t top); +void +PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top); /* - * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it + * Pop tc->topStmt. If the top StmtInfo struct is not stack-allocated, it * is up to the caller to free it. */ -extern void -js_PopStatement(JSTreeContext *tc); +void +PopStatementTC(TreeContext *tc); /* - * Like js_PopStatement(cg), also patch breaks and continues unless the top + * Like PopStatementTC(cg), also patch breaks and continues unless the top * statement info record represents a try-catch-finally suite. May fail if a * jump offset overflows. */ -extern JSBool -js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg); +JSBool +PopStatementCG(JSContext *cx, CodeGenerator *cg); /* * Define and lookup a primitive jsval associated with the const named by atom. - * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn + * DefineCompileTimeConstant analyzes the constant-folded initializer at pn * and saves the const's value in cg->constList, if it can be used at compile * time. It returns true unless an error occurred. * - * If the initializer's value could not be saved, js_DefineCompileTimeConstant - * calls will return the undefined value. js_DefineCompileTimeConstant tries + * If the initializer's value could not be saved, DefineCompileTimeConstant + * calls will return the undefined value. DefineCompileTimeConstant tries * to find a const value memorized for atom, returning true with *vp set to a * value other than undefined if the constant was found, true with *vp set to * JSVAL_VOID if not found, and false on error. */ -extern JSBool -js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - JSParseNode *pn); +JSBool +DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn); /* * Find a lexically scoped variable (one declared by let, catch, or an array @@ -890,26 +887,27 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, * null, then if atom is found, set *slotp to its stack slot, otherwise to -1. * This means that if slotp is not null, all the block objects on the lexical * scope chain must have had their depth slots computed by the code generator, - * so the caller must be under js_EmitTree. + * so the caller must be under EmitTree. * * In any event, directly return the statement info record in which atom was * found. Otherwise return null. */ -extern JSStmtInfo * -js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, - JSStmtInfo *stmt = NULL); +StmtInfo * +LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt = NULL); /* * Emit code into cg for the tree rooted at pn. */ -extern JSBool -js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn); +JSBool +EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn); /* * Emit function code using cg for the tree rooted at body. */ -extern JSBool -js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body); +JSBool +EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body); + +} /* namespace frontend */ /* * Source notes generated along with bytecode for decompiling and debugging. @@ -927,13 +925,13 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body); * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE, * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode. * - * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its - * initializers need to match the order here. + * NB: the js_SrcNoteSpec array in BytecodeGenerator.cpp is indexed by this + * enum, so its initializers need to match the order here. * * Note on adding new source notes: every pair of bytecodes (A, B) where A and * B have disjoint sets of source notes that could apply to each bytecode may * reuse the same note type value for two notes (snA, snB) that have the same - * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is + * arity, offsetBias, and isSpanDep initializers in JSSrcNoteSpec. This is * why SRC_IF and SRC_INITPROP have the same value below. For bad historical * reasons, some bytecodes below that could be overlayed have not been, but * before using SRC_EXTENDED, consider compressing the existing note types. @@ -941,7 +939,7 @@ js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body); * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such * incompatible source note or other bytecode changes. */ -typedef enum JSSrcNoteType { +enum SrcNoteType { SRC_NULL = 0, /* terminates a note vector */ SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */ SRC_BREAK = 1, /* JSOP_GOTO is a break */ @@ -990,7 +988,7 @@ typedef enum JSSrcNoteType { SRC_NEWLINE = 22, /* bytecode follows a source newline */ SRC_SETLINE = 23, /* a file-absolute source line number note */ SRC_XDELTA = 24 /* 24-31 are for extended delta notes */ -} JSSrcNoteType; +}; /* * Constants for the SRC_DECL source note. Note that span-dependent bytecode @@ -1022,9 +1020,9 @@ typedef enum JSSrcNoteType { | ((d) & SN_XDELTA_MASK))) #define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA) -#define SN_TYPE(sn) ((JSSrcNoteType)(SN_IS_XDELTA(sn) \ - ? SRC_XDELTA \ - : *(sn) >> SN_DELTA_BITS)) +#define SN_TYPE(sn) ((js::SrcNoteType)(SN_IS_XDELTA(sn) \ + ? SRC_XDELTA \ + : *(sn) >> SN_DELTA_BITS)) #define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn)) #define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE) @@ -1046,17 +1044,6 @@ typedef enum JSSrcNoteType { #define SN_3BYTE_OFFSET_FLAG 0x80 #define SN_3BYTE_OFFSET_MASK 0x7f -typedef struct JSSrcNoteSpec { - const char *name; /* name for disassembly/debugging output */ - int8 arity; /* number of offset operands */ - uint8 offsetBias; /* bias of offset(s) from annotated pc */ - int8 isSpanDep; /* 1 or -1 if offsets could span extended ops, - 0 otherwise; sign tells span direction */ -} JSSrcNoteSpec; - -extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[]; -extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn); - #define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \ : js_SrcNoteLength(sn)) #define SN_NEXT(sn) ((sn) + SN_LENGTH(sn)) @@ -1065,39 +1052,32 @@ extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn); #define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL) #define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL) +namespace frontend { + /* * Append a new source note of the given type (and therefore size) to cg's * notes dynamic array, updating cg->noteCount. Return the new note's index * within the array pointed at by cg->current->notes. Return -1 if out of * memory. */ -extern intN -js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type); +intN +NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type); -extern intN -js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset); +intN +NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset); -extern intN -js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type, - ptrdiff_t offset1, ptrdiff_t offset2); +intN +NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1, + ptrdiff_t offset2); /* * NB: this function can add at most one extra extended delta note. */ -extern jssrcnote * -js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn, - ptrdiff_t delta); +jssrcnote * +AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta); -/* - * Get and set the offset operand identified by which (0 for the first, etc.). - */ -extern JS_FRIEND_API(ptrdiff_t) -js_GetSrcNoteOffset(jssrcnote *sn, uintN which); - -extern JSBool -js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, - uintN which, ptrdiff_t offset); +JSBool +SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset); /* * Finish taking source notes in cx's notePool, copying final notes to the new @@ -1106,8 +1086,8 @@ js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, * * To compute the number of jssrcnotes to allocate and pass in via notes, use * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of - * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes - * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES! + * FinishTakingSrcNotes, so DON'T CHANGE js::frontend::FinishTakingSrcNotes + * WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES! */ #define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \ JS_BEGIN_MACRO \ @@ -1130,12 +1110,30 @@ js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index, } \ JS_END_MACRO -extern JSBool -js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes); +JSBool +FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes); -extern void -js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array); +void +FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array); -JS_END_EXTERN_C +} /* namespace frontend */ +} /* namespace js */ + +struct JSSrcNoteSpec { + const char *name; /* name for disassembly/debugging output */ + int8 arity; /* number of offset operands */ + uint8 offsetBias; /* bias of offset(s) from annotated pc */ + int8 isSpanDep; /* 1 or -1 if offsets could span extended ops, + 0 otherwise; sign tells span direction */ +}; + +extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[]; +extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn); + +/* + * Get and set the offset operand identified by which (0 for the first, etc.). + */ +extern JS_FRIEND_API(ptrdiff_t) +js_GetSrcNoteOffset(jssrcnote *sn, uintN which); #endif /* BytecodeGenerator_h__ */ diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 79d15e8232ec..c09fb3792801 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -51,10 +51,10 @@ using namespace js; -static JSParseNode * -ContainsStmt(JSParseNode *pn, TokenKind tt) +static ParseNode * +ContainsStmt(ParseNode *pn, TokenKind tt) { - JSParseNode *pn2, *pnt; + ParseNode *pn2, *pnt; if (!pn) return NULL; @@ -105,7 +105,7 @@ ContainsStmt(JSParseNode *pn, TokenKind tt) * XXX handles only strings and numbers for now */ static JSBool -FoldType(JSContext *cx, JSParseNode *pn, TokenKind type) +FoldType(JSContext *cx, ParseNode *pn, TokenKind type) { if (!pn->isKind(type)) { switch (type) { @@ -145,8 +145,8 @@ FoldType(JSContext *cx, JSParseNode *pn, TokenKind type) * a successful call to this function. */ static JSBool -FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2, - JSParseNode *pn, JSTreeContext *tc) +FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2, + ParseNode *pn, TreeContext *tc) { jsdouble d, d2; int32 i, j; @@ -213,9 +213,9 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2, /* Take care to allow pn1 or pn2 to alias pn. */ if (pn1 != pn) - RecycleTree(pn1, tc); + tc->freeTree(pn1); if (pn2 != pn) - RecycleTree(pn2, tc); + tc->freeTree(pn2); pn->setKind(TOK_NUMBER); pn->setOp(JSOP_DOUBLE); pn->setArity(PN_NULLARY); @@ -226,10 +226,10 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2, #if JS_HAS_XML_SUPPORT static JSBool -FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) +FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc) { TokenKind tt; - JSParseNode **pnp, *pn1, *pn2; + ParseNode **pnp, *pn1, *pn2; JSString *accum, *str; uint32 i, j; @@ -303,7 +303,7 @@ FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) #endif } else if (accum && pn1 != pn2) { while (pn1->pn_next != pn2) { - pn1 = RecycleTree(pn1, tc); + pn1 = tc->freeTree(pn1); --pn->pn_count; } pn1->setKind(TOK_XMLTEXT); @@ -356,7 +356,7 @@ FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) JS_ASSERT(*pnp == pn1); while (pn1->pn_next) { - pn1 = RecycleTree(pn1, tc); + pn1 = tc->freeTree(pn1); --pn->pn_count; } pn1->setKind(TOK_XMLTEXT); @@ -392,7 +392,7 @@ FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) enum Truthiness { Truthy, Falsy, Unknown }; static Truthiness -Boolish(JSParseNode *pn) +Boolish(ParseNode *pn) { switch (pn->getOp()) { case JSOP_DOUBLE: @@ -411,7 +411,7 @@ Boolish(JSParseNode *pn) */ if (pn->pn_count != 1) return Unknown; - JSParseNode *pn2 = pn->pn_head; + ParseNode *pn2 = pn->pn_head; if (!pn2->isKind(TOK_FUNCTION)) return Unknown; if (!(pn2->pn_funbox->tcflags & TCF_GENEXP_LAMBDA)) @@ -434,23 +434,25 @@ Boolish(JSParseNode *pn) } } -JSBool -js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) -{ - JSParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL; +namespace js { - JS_CHECK_RECURSION(cx, return JS_FALSE); +bool +FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond) +{ + ParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL; + + JS_CHECK_RECURSION(cx, return false); switch (pn->getArity()) { case PN_FUNC: { uint32 oldflags = tc->flags; - JSFunctionBox *oldlist = tc->functionList; + FunctionBox *oldlist = tc->functionList; tc->flags = pn->pn_funbox->tcflags; tc->functionList = pn->pn_funbox->kids; - if (!js_FoldConstants(cx, pn->pn_body, tc)) - return JS_FALSE; + if (!FoldConstants(cx, pn->pn_body, tc)) + return false; pn->pn_funbox->kids = tc->functionList; tc->flags = oldflags; tc->functionList = oldlist; @@ -469,8 +471,8 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) /* Save the list head in pn1 for later use. */ for (; pn2; pn2 = pn2->pn_next) { - if (!js_FoldConstants(cx, pn2, tc, cond)) - return JS_FALSE; + if (!FoldConstants(cx, pn2, tc, cond)) + return false; } break; } @@ -480,18 +482,18 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) pn1 = pn->pn_kid1; pn2 = pn->pn_kid2; pn3 = pn->pn_kid3; - if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->isKind(TOK_IF))) - return JS_FALSE; + if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(TOK_IF))) + return false; if (pn2) { - if (!js_FoldConstants(cx, pn2, tc, pn->isKind(TOK_FORHEAD))) - return JS_FALSE; + if (!FoldConstants(cx, pn2, tc, pn->isKind(TOK_FORHEAD))) + return false; if (pn->isKind(TOK_FORHEAD) && pn2->isOp(JSOP_TRUE)) { - RecycleTree(pn2, tc); + tc->freeTree(pn2); pn->pn_kid2 = NULL; } } - if (pn3 && !js_FoldConstants(cx, pn3, tc)) - return JS_FALSE; + if (pn3 && !FoldConstants(cx, pn3, tc)) + return false; break; case PN_BINARY: @@ -500,18 +502,18 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) /* Propagate inCond through logical connectives. */ if (pn->isKind(TOK_OR) || pn->isKind(TOK_AND)) { - if (!js_FoldConstants(cx, pn1, tc, inCond)) - return JS_FALSE; - if (!js_FoldConstants(cx, pn2, tc, inCond)) - return JS_FALSE; + if (!FoldConstants(cx, pn1, tc, inCond)) + return false; + if (!FoldConstants(cx, pn2, tc, inCond)) + return false; break; } /* First kid may be null (for default case in switch). */ - if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->isKind(TOK_WHILE))) - return JS_FALSE; - if (!js_FoldConstants(cx, pn2, tc, pn->isKind(TOK_DO))) - return JS_FALSE; + if (pn1 && !FoldConstants(cx, pn1, tc, pn->isKind(TOK_WHILE))) + return false; + if (!FoldConstants(cx, pn2, tc, pn->isKind(TOK_DO))) + return false; break; case PN_UNARY: @@ -529,8 +531,8 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) if (pn->isOp(JSOP_TYPEOF) && !pn1->isKind(TOK_NAME)) pn->setOp(JSOP_TYPEOFEXPR); - if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->isOp(JSOP_NOT))) - return JS_FALSE; + if (pn1 && !FoldConstants(cx, pn1, tc, pn->isOp(JSOP_NOT))) + return false; break; case PN_NAME: @@ -544,15 +546,15 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) pn1 = pn->pn_expr; while (pn1 && pn1->isArity(PN_NAME) && !pn1->isUsed()) pn1 = pn1->pn_expr; - if (pn1 && !js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; + if (pn1 && !FoldConstants(cx, pn1, tc)) + return false; } break; case PN_NAMESET: pn1 = pn->pn_tree; - if (!js_FoldConstants(cx, pn1, tc)) - return JS_FALSE; + if (!FoldConstants(cx, pn1, tc)) + return false; break; case PN_NULLARY: @@ -586,7 +588,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) /* FALL THROUGH */ default: /* Early return to dodge common code that copies pn2 to pn. */ - return JS_TRUE; + return true; } #if JS_HAS_GENERATOR_EXPRS @@ -609,16 +611,16 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) pn->setArity(PN_LIST); pn->makeEmpty(); } - RecycleTree(pn2, tc); + tc->freeTree(pn2); if (pn3 && pn3 != pn2) - RecycleTree(pn3, tc); + tc->freeTree(pn3); break; case TOK_OR: case TOK_AND: if (inCond) { if (pn->isArity(PN_LIST)) { - JSParseNode **pnp = &pn->pn_head; + ParseNode **pnp = &pn->pn_head; JS_ASSERT(*pnp == pn1); do { Truthiness t = Boolish(pn1); @@ -629,7 +631,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) if ((t == Truthy) == pn->isKind(TOK_OR)) { for (pn2 = pn1->pn_next; pn2; pn2 = pn3) { pn3 = pn2->pn_next; - RecycleTree(pn2, tc); + tc->freeTree(pn2); --pn->pn_count; } pn1->pn_next = NULL; @@ -639,7 +641,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) if (pn->pn_count == 1) break; *pnp = pn1->pn_next; - RecycleTree(pn1, tc); + tc->freeTree(pn1); --pn->pn_count; } while ((pn1 = *pnp) != NULL); @@ -654,17 +656,17 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) pn->pn_right = pn2; } else if (pn->pn_count == 1) { pn->become(pn1); - RecycleTree(pn1, tc); + tc->freeTree(pn1); } } else { Truthiness t = Boolish(pn1); if (t != Unknown) { if ((t == Truthy) == pn->isKind(TOK_OR)) { - RecycleTree(pn2, tc); + tc->freeTree(pn2); pn->become(pn1); } else { JS_ASSERT((t == Truthy) == pn->isKind(TOK_AND)); - RecycleTree(pn1, tc); + tc->freeTree(pn1); pn->become(pn2); } } @@ -694,7 +696,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) */ JS_ASSERT(pn->pn_count > 2); if (pn->pn_xflags & PNX_CANTFOLD) - return JS_TRUE; + return true; if (pn->pn_xflags != PNX_STRCAT) goto do_binary_op; @@ -702,26 +704,26 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) size_t length = 0; for (pn2 = pn1; pn2; pn2 = pn2->pn_next) { if (!FoldType(cx, pn2, TOK_STRING)) - return JS_FALSE; + return false; /* XXX fold only if all operands convert to string */ if (!pn2->isKind(TOK_STRING)) - return JS_TRUE; + return true; length += pn2->pn_atom->length(); } /* Allocate a new buffer and string descriptor for the result. */ jschar *chars = (jschar *) cx->malloc_((length + 1) * sizeof(jschar)); if (!chars) - return JS_FALSE; + return false; chars[length] = 0; JSString *str = js_NewString(cx, chars, length); if (!str) { cx->free_(chars); - return JS_FALSE; + return false; } /* Fill the buffer, advancing chars and recycling kids as we go. */ - for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) { + for (pn2 = pn1; pn2; pn2 = tc->freeTree(pn2)) { JSAtom *atom = pn2->pn_atom; size_t length2 = atom->length(); js_strncpy(chars, atom->chars(), length2); @@ -732,7 +734,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) /* Atomize the result string and mutate pn to refer to it. */ pn->pn_atom = js_AtomizeString(cx, str); if (!pn->pn_atom) - return JS_FALSE; + return false; pn->setKind(TOK_STRING); pn->setOp(JSOP_STRING); pn->setArity(PN_NULLARY); @@ -745,22 +747,22 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) JSString *left, *right, *str; if (!FoldType(cx, !pn1->isKind(TOK_STRING) ? pn1 : pn2, TOK_STRING)) - return JS_FALSE; + return false; if (!pn1->isKind(TOK_STRING) || !pn2->isKind(TOK_STRING)) - return JS_TRUE; + return true; left = pn1->pn_atom; right = pn2->pn_atom; str = js_ConcatStrings(cx, left, right); if (!str) - return JS_FALSE; + return false; pn->pn_atom = js_AtomizeString(cx, str); if (!pn->pn_atom) - return JS_FALSE; + return false; pn->setKind(TOK_STRING); pn->setOp(JSOP_STRING); pn->setArity(PN_NULLARY); - RecycleTree(pn1, tc); - RecycleTree(pn2, tc); + tc->freeTree(pn1); + tc->freeTree(pn2); break; } @@ -776,7 +778,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) JS_ASSERT(pn->pn_count > 2); for (pn2 = pn1; pn2; pn2 = pn2->pn_next) { if (!FoldType(cx, pn2, TOK_NUMBER)) - return JS_FALSE; + return false; } for (pn2 = pn1; pn2; pn2 = pn2->pn_next) { /* XXX fold only if all operands convert to number */ @@ -789,22 +791,22 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) pn2 = pn1->pn_next; pn3 = pn2->pn_next; if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, tc)) - return JS_FALSE; + return false; while ((pn2 = pn3) != NULL) { pn3 = pn2->pn_next; if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, tc)) - return JS_FALSE; + return false; } } } else { JS_ASSERT(pn->isArity(PN_BINARY)); if (!FoldType(cx, pn1, TOK_NUMBER) || !FoldType(cx, pn2, TOK_NUMBER)) { - return JS_FALSE; + return false; } if (pn1->isKind(TOK_NUMBER) && pn2->isKind(TOK_NUMBER)) { if (!FoldBinaryNumeric(cx, pn->getOp(), pn1, pn2, pn, tc)) - return JS_FALSE; + return false; } } break; @@ -835,18 +837,18 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) default: /* Return early to dodge the common TOK_NUMBER code. */ - return JS_TRUE; + return true; } pn->setKind(TOK_NUMBER); pn->setOp(JSOP_DOUBLE); pn->setArity(PN_NULLARY); pn->pn_dval = d; - RecycleTree(pn1, tc); + tc->freeTree(pn1); } else if (pn1->isKind(TOK_PRIMARY)) { if (pn->isOp(JSOP_NOT) && (pn1->isOp(JSOP_TRUE) || pn1->isOp(JSOP_FALSE))) { pn->become(pn1); pn->setOp(pn->isOp(JSOP_TRUE) ? JSOP_FALSE : JSOP_TRUE); - RecycleTree(pn1, tc); + tc->freeTree(pn1); } } break; @@ -861,28 +863,26 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) if (pn->isArity(PN_LIST)) { JS_ASSERT(pn->isKind(TOK_XMLLIST) || pn->pn_count != 0); if (!FoldXMLConstants(cx, pn, tc)) - return JS_FALSE; + return false; } break; case TOK_AT: if (pn1->isKind(TOK_XMLNAME)) { - JSObjectBox *xmlbox; - Value v = StringValue(pn1->pn_atom); if (!js_ToAttributeName(cx, &v)) - return JS_FALSE; + return false; JS_ASSERT(v.isObject()); - xmlbox = tc->parser->newObjectBox(&v.toObject()); + ObjectBox *xmlbox = tc->parser->newObjectBox(&v.toObject()); if (!xmlbox) - return JS_FALSE; + return false; pn->setKind(TOK_XMLNAME); pn->setOp(JSOP_OBJECT); pn->setArity(PN_NULLARY); pn->pn_objbox = xmlbox; - RecycleTree(pn1, tc); + tc->freeTree(pn1); } break; #endif /* JS_HAS_XML_SUPPORT */ @@ -899,12 +899,14 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond) * a method list corrupts the method list. However, methods are M's in * statements of the form 'this.foo = M;', which we never fold, so we're okay. */ - PrepareNodeForMutation(pn, tc); + tc->parser->allocator.prepareNodeForMutation(pn); pn->setKind(TOK_PRIMARY); pn->setOp(t == Truthy ? JSOP_TRUE : JSOP_FALSE); pn->setArity(PN_NULLARY); } } - return JS_TRUE; + return true; } + +} /* namespace js */ diff --git a/js/src/frontend/FoldConstants.h b/js/src/frontend/FoldConstants.h index 98ee37821ce1..1496107bb035 100644 --- a/js/src/frontend/FoldConstants.h +++ b/js/src/frontend/FoldConstants.h @@ -43,12 +43,11 @@ #include "jsprvtd.h" -JS_BEGIN_EXTERN_C +namespace js { -extern JSBool -js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, - bool inCond = false); +bool +FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond = false); -JS_END_EXTERN_C +} /* namespace js */ #endif /* FoldConstants_h__ */ diff --git a/js/src/frontend/ParseMaps-inl.h b/js/src/frontend/ParseMaps-inl.h index caa3ae9ebd1b..13fb7d33321d 100644 --- a/js/src/frontend/ParseMaps-inl.h +++ b/js/src/frontend/ParseMaps-inl.h @@ -43,7 +43,7 @@ #include "jscntxt.h" -#include "frontend/ParseNode.h" /* Need sizeof(JSDefinition). */ +#include "frontend/ParseNode.h" /* Need sizeof(js::Definition). */ #include "ParseMaps.h" @@ -81,7 +81,7 @@ ParseMapPool::allocate() return map; } -inline JSDefinition * +inline Definition * AtomDecls::lookupFirst(JSAtom *atom) { JS_ASSERT(map); @@ -101,7 +101,7 @@ AtomDecls::lookupMulti(JSAtom *atom) JS_ASSERT(map); AtomDOHPtr p = map->lookup(atom); if (!p) - return MultiDeclRange((JSDefinition *) NULL); + return MultiDeclRange((Definition *) NULL); DefnOrHeader &doh = p.value(); if (doh.isHeader()) @@ -110,7 +110,7 @@ AtomDecls::lookupMulti(JSAtom *atom) } inline bool -AtomDecls::addUnique(JSAtom *atom, JSDefinition *defn) +AtomDecls::addUnique(JSAtom *atom, Definition *defn) { JS_ASSERT(map); AtomDOHAddPtr p = map->lookupForAdd(atom); diff --git a/js/src/frontend/ParseMaps.cpp b/js/src/frontend/ParseMaps.cpp index edc5623715a4..ab6c345ee4ee 100644 --- a/js/src/frontend/ParseMaps.cpp +++ b/js/src/frontend/ParseMaps.cpp @@ -50,8 +50,8 @@ ParseMapPool::checkInvariants() * Having all values be of the same size permits us to easily reuse the * allocated space for each of the map types. */ - JS_STATIC_ASSERT(sizeof(JSDefinition *) == sizeof(jsatomid)); - JS_STATIC_ASSERT(sizeof(JSDefinition *) == sizeof(DefnOrHeader)); + JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(jsatomid)); + JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(DefnOrHeader)); JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomIndexMap::Entry)); JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomDOHMap::Entry)); JS_STATIC_ASSERT(sizeof(AtomMapT::Entry) == sizeof(AtomDOHMap::Entry)); @@ -124,7 +124,7 @@ DumpAtomDefnMap(const AtomDefnMapPtr &map) #endif AtomDeclNode * -AtomDecls::allocNode(JSDefinition *defn) +AtomDecls::allocNode(Definition *defn) { AtomDeclNode *p = cx->tempLifoAlloc().new_(defn); if (!p) { @@ -135,7 +135,7 @@ AtomDecls::allocNode(JSDefinition *defn) } bool -AtomDecls::addShadow(JSAtom *atom, JSDefinition *defn) +AtomDecls::addShadow(JSAtom *atom, Definition *defn) { AtomDeclNode *node = allocNode(defn); if (!node) @@ -177,7 +177,7 @@ AtomDecls::lastAsNode(DefnOrHeader *doh) } bool -AtomDecls::addHoist(JSAtom *atom, JSDefinition *defn) +AtomDecls::addHoist(JSAtom *atom, Definition *defn) { AtomDeclNode *node = allocNode(defn); if (!node) diff --git a/js/src/frontend/ParseMaps.h b/js/src/frontend/ParseMaps.h index 3b7800816476..296d83b4d3e8 100644 --- a/js/src/frontend/ParseMaps.h +++ b/js/src/frontend/ParseMaps.h @@ -47,6 +47,8 @@ namespace js { +struct Definition; + /* * A pool that permits the reuse of the backing storage for the defn, index, or * defn-or-header (multi) maps. @@ -126,7 +128,7 @@ class ParseMapPool }; /* ParseMapPool */ /* - * N.B. This is a POD-type so that it can be included in the JSParseNode union. + * N.B. This is a POD-type so that it can be included in the ParseNode union. * If possible, use the corresponding |OwnedAtomThingMapPtr| variant. */ template @@ -152,7 +154,7 @@ struct AtomThingMapPtr struct AtomDefnMapPtr : public AtomThingMapPtr { JS_ALWAYS_INLINE - JSDefinition *lookupDefn(JSAtom *atom) { + Definition *lookupDefn(JSAtom *atom) { AtomDefnMap::Ptr p = map_->lookup(atom); return p ? p.value() : NULL; } @@ -185,22 +187,22 @@ typedef OwnedAtomThingMapPtr OwnedAtomIndexMapPtr; /* Node structure for chaining in AtomDecls. */ struct AtomDeclNode { - JSDefinition *defn; + Definition *defn; AtomDeclNode *next; - explicit AtomDeclNode(JSDefinition *defn) + explicit AtomDeclNode(Definition *defn) : defn(defn), next(NULL) {} }; /* - * Tagged union of a JSDefinition and an AtomDeclNode, for use in AtomDecl's + * Tagged union of a Definition and an AtomDeclNode, for use in AtomDecl's * internal map. */ class DefnOrHeader { union { - JSDefinition *defn; + Definition *defn; AtomDeclNode *head; uintptr_t bits; } u; @@ -210,7 +212,7 @@ class DefnOrHeader u.bits = 0; } - explicit DefnOrHeader(JSDefinition *defn) { + explicit DefnOrHeader(Definition *defn) { u.defn = defn; JS_ASSERT(!isHeader()); } @@ -225,7 +227,7 @@ class DefnOrHeader return u.bits & 0x1; } - JSDefinition *defn() const { + Definition *defn() const { JS_ASSERT(!isHeader()); return u.defn; } @@ -268,7 +270,7 @@ class AtomDecls AtomDecls(const AtomDecls &other); void operator=(const AtomDecls &other); - AtomDeclNode *allocNode(JSDefinition *defn); + AtomDeclNode *allocNode(Definition *defn); /* * Fallibly return the value in |doh| as a node. @@ -290,18 +292,18 @@ class AtomDecls } /* Return the definition at the head of the chain for |atom|. */ - inline JSDefinition *lookupFirst(JSAtom *atom); + inline Definition *lookupFirst(JSAtom *atom); /* Perform a lookup that can iterate over the definitions associated with |atom|. */ inline MultiDeclRange lookupMulti(JSAtom *atom); /* Add-or-update a known-unique definition for |atom|. */ - inline bool addUnique(JSAtom *atom, JSDefinition *defn); - bool addShadow(JSAtom *atom, JSDefinition *defn); - bool addHoist(JSAtom *atom, JSDefinition *defn); + inline bool addUnique(JSAtom *atom, Definition *defn); + bool addShadow(JSAtom *atom, Definition *defn); + bool addHoist(JSAtom *atom, Definition *defn); /* Updating the definition for an entry that is known to exist is infallible. */ - void updateFirst(JSAtom *atom, JSDefinition *defn) { + void updateFirst(JSAtom *atom, Definition *defn) { JS_ASSERT(map); AtomDOHMap::Ptr p = map->lookup(atom); JS_ASSERT(p); @@ -352,9 +354,9 @@ class MultiDeclRange friend class AtomDecls; AtomDeclNode *node; - JSDefinition *defn; + Definition *defn; - explicit MultiDeclRange(JSDefinition *defn) : node(NULL), defn(defn) {} + explicit MultiDeclRange(Definition *defn) : node(NULL), defn(defn) {} explicit MultiDeclRange(AtomDeclNode *node) : node(node), defn(node->defn) {} public: @@ -368,7 +370,7 @@ class MultiDeclRange defn = node ? node->defn : NULL; } - JSDefinition *front() { + Definition *front() { JS_ASSERT(!empty()); return defn; } @@ -388,10 +390,10 @@ class AtomDeclsIter public: explicit AtomDeclsIter(AtomDecls *decls) : r(decls->all()), link(NULL) {} - JSDefinition *operator()() { + Definition *operator()() { if (link) { JS_ASSERT(link != link->next); - JSDefinition *result = link->defn; + Definition *result = link->defn; link = link->next; JS_ASSERT(result); return result; diff --git a/js/src/frontend/ParseNode-inl.h b/js/src/frontend/ParseNode-inl.h index df16a46ae1c2..51e62b001c5a 100644 --- a/js/src/frontend/ParseNode-inl.h +++ b/js/src/frontend/ParseNode-inl.h @@ -44,11 +44,11 @@ #include "frontend/BytecodeGenerator.h" #include "frontend/TokenStream.h" -inline bool -JSParseNode::isConstant() -{ - using namespace js; +namespace js { +inline bool +ParseNode::isConstant() +{ switch (pn_type) { case TOK_NUMBER: case TOK_STRING: @@ -70,10 +70,8 @@ JSParseNode::isConstant() } } -namespace js { - inline void -NameNode::initCommon(JSTreeContext *tc) +NameNode::initCommon(TreeContext *tc) { pn_expr = NULL; pn_cookie.makeFree(); diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 93fe0bedab3e..1147a25c193e 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -40,9 +40,6 @@ #include "frontend/ParseNode.h" -#include "frontend/BytecodeGenerator.h" -#include "frontend/Parser.h" - #include "jsscriptinlines.h" #include "frontend/ParseMaps-inl.h" @@ -53,21 +50,23 @@ using namespace js; /* * Asserts to verify assumptions behind pn_ macros. */ -#define pn_offsetof(m) offsetof(JSParseNode, m) +#define pn_offsetof(m) offsetof(ParseNode, m) JS_STATIC_ASSERT(pn_offsetof(pn_link) == pn_offsetof(dn_uses)); #undef pn_offsetof +namespace js { + void -JSParseNode::become(JSParseNode *pn2) +ParseNode::become(ParseNode *pn2) { JS_ASSERT(!pn_defn); JS_ASSERT(!pn2->isDefn()); JS_ASSERT(!pn_used); if (pn2->isUsed()) { - JSParseNode **pnup = &pn2->pn_lexdef->dn_uses; + ParseNode **pnup = &pn2->pn_lexdef->dn_uses; while (*pnup != pn2) pnup = &(*pnup)->pn_link; *pnup = this; @@ -102,7 +101,7 @@ JSParseNode::become(JSParseNode *pn2) } void -JSParseNode::clear() +ParseNode::clear() { pn_type = TOK_EOF; setOp(JSOP_NOP); @@ -111,9 +110,8 @@ JSParseNode::clear() pn_parens = false; } - bool -JSFunctionBox::joinable() const +FunctionBox::joinable() const { return function()->isNullClosure() && (tcflags & (TCF_FUN_USES_ARGUMENTS | @@ -122,9 +120,9 @@ JSFunctionBox::joinable() const } bool -JSFunctionBox::inAnyDynamicScope() const +FunctionBox::inAnyDynamicScope() const { - for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) { + for (const FunctionBox *funbox = this; funbox; funbox = funbox->parent) { if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_EXTENSIBLE_SCOPE)) return true; } @@ -132,16 +130,16 @@ JSFunctionBox::inAnyDynamicScope() const } bool -JSFunctionBox::scopeIsExtensible() const +FunctionBox::scopeIsExtensible() const { return tcflags & TCF_FUN_EXTENSIBLE_SCOPE; } bool -JSFunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const +FunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const { if (slowMethods != 0) { - for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) { + for (const FunctionBox *funbox = this; funbox; funbox = funbox->parent) { if (!(funbox->tcflags & TCF_FUN_MODULE_PATTERN)) return true; if (funbox->inLoop) @@ -151,14 +149,12 @@ JSFunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const return false; } -namespace js { - /* Add |node| to |parser|'s free node list. */ void -AddNodeToFreeList(JSParseNode *pn, js::Parser *parser) +ParseNodeAllocator::freeNode(ParseNode *pn) { /* Catch back-to-back dup recycles. */ - JS_ASSERT(pn != parser->nodeList); + JS_ASSERT(pn != freelist); /* * It's too hard to clear these nodes from the AtomDefnMaps, etc. that @@ -170,19 +166,19 @@ AddNodeToFreeList(JSParseNode *pn, js::Parser *parser) JS_ASSERT(!pn->isDefn()); if (pn->isArity(PN_NAMESET) && pn->pn_names.hasMap()) - pn->pn_names.releaseMap(parser->context); + pn->pn_names.releaseMap(cx); #ifdef DEBUG /* Poison the node, to catch attempts to use it without initializing it. */ memset(pn, 0xab, sizeof(*pn)); #endif - pn->pn_next = parser->nodeList; - parser->nodeList = pn; + pn->pn_next = freelist; + freelist = pn; } /* - * A work pool of JSParseNodes. The work pool is a stack, chained together + * A work pool of ParseNodes. The work pool is a stack, chained together * by nodes' pn_next fields. We use this to avoid creating deep C++ stacks * when recycling deep parse trees. * @@ -194,59 +190,56 @@ class NodeStack { public: NodeStack() : top(NULL) { } bool empty() { return top == NULL; } - void push(JSParseNode *pn) { + void push(ParseNode *pn) { pn->pn_next = top; top = pn; } - void pushUnlessNull(JSParseNode *pn) { if (pn) push(pn); } + void pushUnlessNull(ParseNode *pn) { if (pn) push(pn); } /* Push the children of the PN_LIST node |pn| on the stack. */ - void pushList(JSParseNode *pn) { + void pushList(ParseNode *pn) { /* This clobbers pn->pn_head if the list is empty; should be okay. */ *pn->pn_tail = top; top = pn->pn_head; } - JSParseNode *pop() { + ParseNode *pop() { JS_ASSERT(!empty()); - JSParseNode *hold = top; /* my kingdom for a prog1 */ + ParseNode *hold = top; /* my kingdom for a prog1 */ top = top->pn_next; return hold; } private: - JSParseNode *top; + ParseNode *top; }; -} /* namespace js */ - /* * Push the children of |pn| on |stack|. Return true if |pn| itself could be * safely recycled, or false if it must be cleaned later (pn_used and pn_defn * nodes, and all function nodes; see comments for * js::Parser::cleanFunctionList). Some callers want to free |pn|; others - * (PrepareNodeForMutation) don't care about |pn|, and just need to take care of - * its children. + * (js::ParseNodeAllocator::prepareNodeForMutation) don't care about |pn|, and + * just need to take care of its children. */ static bool -PushNodeChildren(JSParseNode *pn, NodeStack *stack) +PushNodeChildren(ParseNode *pn, NodeStack *stack) { switch (pn->getArity()) { case PN_FUNC: /* - * Function nodes are linked into the function box tree, and may - * appear on method lists. Both of those lists are singly-linked, - * so trying to update them now could result in quadratic behavior - * when recycling trees containing many functions; and the lists - * can be very long. So we put off cleaning the lists up until just - * before function analysis, when we call - * js::Parser::cleanFunctionList. + * Function nodes are linked into the function box tree, and may appear + * on method lists. Both of those lists are singly-linked, so trying to + * update them now could result in quadratic behavior when recycling + * trees containing many functions; and the lists can be very long. So + * we put off cleaning the lists up until just before function + * analysis, when we call js::Parser::cleanFunctionList. * - * In fact, we can't recycle the parse node yet, either: it may - * appear on a method list, and reusing the node would corrupt - * that. Instead, we clear its pn_funbox pointer to mark it as - * deleted; js::Parser::cleanFunctionList recycles it as well. + * In fact, we can't recycle the parse node yet, either: it may appear + * on a method list, and reusing the node would corrupt that. Instead, + * we clear its pn_funbox pointer to mark it as deleted; + * js::Parser::cleanFunctionList recycles it as well. * - * We do recycle the nodes around it, though, so we must clear - * pointers to them to avoid leaving dangling references where - * someone can find them. + * We do recycle the nodes around it, though, so we must clear pointers + * to them to avoid leaving dangling references where someone can find + * them. */ pn->pn_funbox = NULL; stack->pushUnlessNull(pn->pn_body); @@ -256,12 +249,11 @@ PushNodeChildren(JSParseNode *pn, NodeStack *stack) case PN_NAME: /* * Because used/defn nodes appear in AtomDefnMaps and elsewhere, we - * don't recycle them. (We'll recover their storage when we free - * the temporary arena.) However, we do recycle the nodes around - * them, so clean up the pointers to avoid dangling references. The - * top-level decls table carries references to them that later - * iterations through the compileScript loop may find, so they need - * to be neat. + * don't recycle them. (We'll recover their storage when we free the + * temporary arena.) However, we do recycle the nodes around them, so + * clean up the pointers to avoid dangling references. The top-level + * decls table carries references to them that later iterations through + * the compileScript loop may find, so they need to be neat. * * pn_expr and pn_lexdef share storage; the latter isn't an owning * reference. @@ -301,15 +293,13 @@ PushNodeChildren(JSParseNode *pn, NodeStack *stack) return true; } -namespace js { - /* * Prepare |pn| to be mutated in place into a new kind of node. Recycle all * |pn|'s recyclable children (but not |pn| itself!), and disconnect it from * metadata structures (the function box tree). */ void -PrepareNodeForMutation(JSParseNode *pn, JSTreeContext *tc) +ParseNodeAllocator::prepareNodeForMutation(ParseNode *pn) { if (!pn->isArity(PN_NULLARY)) { if (pn->isArity(PN_FUNC)) { @@ -340,7 +330,7 @@ PrepareNodeForMutation(JSParseNode *pn, JSTreeContext *tc) while (!stack.empty()) { pn = stack.pop(); if (PushNodeChildren(pn, &stack)) - AddNodeToFreeList(pn, tc->parser); + freeNode(pn); } } } @@ -355,18 +345,18 @@ PrepareNodeForMutation(JSParseNode *pn, JSTreeContext *tc) * recycle some part of it (unless you've updated |tc|->functionList, the * way js_FoldConstants does). */ -JSParseNode * -RecycleTree(JSParseNode *pn, JSTreeContext *tc) +ParseNode * +ParseNodeAllocator::freeTree(ParseNode *pn) { if (!pn) return NULL; - JSParseNode *savedNext = pn->pn_next; + ParseNode *savedNext = pn->pn_next; NodeStack stack; for (;;) { if (PushNodeChildren(pn, &stack)) - AddNodeToFreeList(pn, tc->parser); + freeNode(pn); if (stack.empty()) break; pn = stack.pop(); @@ -376,62 +366,37 @@ RecycleTree(JSParseNode *pn, JSTreeContext *tc) } /* - * Allocate a JSParseNode from tc's node freelist or, failing that, from + * Allocate a ParseNode from parser's node freelist or, failing that, from * cx's temporary arena. */ -JSParseNode * -NewOrRecycledNode(JSTreeContext *tc) +void * +ParseNodeAllocator::allocNode() { - JSParseNode *pn; - - pn = tc->parser->nodeList; - if (!pn) { - JSContext *cx = tc->parser->context; - pn = cx->tempLifoAlloc().new_(); - if (!pn) - js_ReportOutOfMemory(cx); - } else { - tc->parser->nodeList = pn->pn_next; + if (ParseNode *pn = freelist) { + freelist = pn->pn_next; + return pn; } - if (pn) { - pn->setUsed(false); - pn->setDefn(false); - memset(&pn->pn_u, 0, sizeof pn->pn_u); - pn->pn_next = NULL; - } - return pn; + void *p = cx->tempLifoAlloc().alloc(sizeof (ParseNode)); + if (!p) + js_ReportOutOfMemory(cx); + return p; } -} /* namespace js */ - /* used only by static create methods of subclasses */ -JSParseNode * -JSParseNode::create(JSParseNodeArity arity, JSTreeContext *tc) +ParseNode * +ParseNode::create(ParseNodeArity arity, TreeContext *tc) { - const Token &tok = tc->parser->tokenStream.currentToken(); - return create(arity, tok.type, JSOP_NOP, tok.pos, tc); + Parser *parser = tc->parser; + const Token &tok = parser->tokenStream.currentToken(); + return parser->new_(tok.type, JSOP_NOP, arity, tok.pos); } -JSParseNode * -JSParseNode::create(JSParseNodeArity arity, TokenKind type, JSOp op, const TokenPos &pos, - JSTreeContext *tc) +ParseNode * +ParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right, + TreeContext *tc) { - JSParseNode *pn = NewOrRecycledNode(tc); - if (!pn) - return NULL; - pn->init(type, op, arity); - pn->pn_pos = pos; - return pn; -} - -JSParseNode * -JSParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, JSParseNode *left, JSParseNode *right, - JSTreeContext *tc) -{ - JSParseNode *pn, *pn1, *pn2; - if (!left || !right) return NULL; @@ -439,11 +404,9 @@ JSParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, JSParseNode *left, JSParse * Flatten a left-associative (left-heavy) tree of a given operator into * a list, to reduce js_FoldConstants and js_EmitTree recursion. */ - if (left->isKind(tt) && - left->isOp(op) && - (js_CodeSpec[op].format & JOF_LEFTASSOC)) { + if (left->isKind(tt) && left->isOp(op) && (js_CodeSpec[op].format & JOF_LEFTASSOC)) { if (left->pn_arity != PN_LIST) { - pn1 = left->pn_left, pn2 = left->pn_right; + ParseNode *pn1 = left->pn_left, *pn2 = left->pn_right; left->setArity(PN_LIST); left->pn_parens = false; left->initList(pn1); @@ -480,32 +443,21 @@ JSParseNode::newBinaryOrAppend(TokenKind tt, JSOp op, JSParseNode *left, JSParse if (tt == TOK_PLUS && left->isKind(TOK_NUMBER) && right->isKind(TOK_NUMBER) && - tc->parser->foldConstants) { + tc->parser->foldConstants) + { left->pn_dval += right->pn_dval; left->pn_pos.end = right->pn_pos.end; - RecycleTree(right, tc); + tc->freeTree(right); return left; } - pn = NewOrRecycledNode(tc); - if (!pn) - return NULL; - pn->init(tt, op, PN_BINARY); - pn->pn_pos.begin = left->pn_pos.begin; - pn->pn_pos.end = right->pn_pos.end; - pn->pn_left = left; - pn->pn_right = right; - return pn; + return tc->parser->new_(tt, op, left, right); } -namespace js { - NameNode * -NameNode::create(JSAtom *atom, JSTreeContext *tc) +NameNode::create(JSAtom *atom, TreeContext *tc) { - JSParseNode *pn; - - pn = JSParseNode::create(PN_NAME, tc); + ParseNode *pn = ParseNode::create(PN_NAME, tc); if (pn) { pn->pn_atom = atom; ((NameNode *)pn)->initCommon(tc); @@ -519,8 +471,10 @@ const char js_argument_str[] = "argument"; const char js_variable_str[] = "variable"; const char js_unknown_str[] = "unknown"; +namespace js { + const char * -JSDefinition::kindString(Kind kind) +Definition::kindString(Kind kind) { static const char *table[] = { js_var_str, js_const_str, js_let_str, @@ -537,23 +491,18 @@ JSDefinition::kindString(Kind kind) * This function assumes the cloned tree is for use in the same statement and * binding context as the original tree. */ -static JSParseNode * -CloneParseTree(JSParseNode *opn, JSTreeContext *tc) +static ParseNode * +CloneParseTree(ParseNode *opn, TreeContext *tc) { JS_CHECK_RECURSION(tc->parser->context, return NULL); - JSParseNode *pn, *pn2, *opn2; - - pn = NewOrRecycledNode(tc); + ParseNode *pn = tc->parser->new_(opn->getKind(), opn->getOp(), opn->getArity(), + opn->pn_pos); if (!pn) return NULL; - pn->setKind(opn->getKind()); - pn->setOp(opn->getOp()); - pn->setUsed(opn->isUsed()); - pn->setDefn(opn->isDefn()); - pn->setArity(opn->getArity()); pn->setInParens(opn->isInParens()); - pn->pn_pos = opn->pn_pos; + pn->setDefn(opn->isDefn()); + pn->setUsed(opn->isUsed()); switch (pn->getArity()) { #define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO @@ -569,7 +518,8 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc) case PN_LIST: pn->makeEmpty(); - for (opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) { + for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) { + ParseNode *pn2; NULLCHECK(pn2 = CloneParseTree(opn2, tc)); pn->append(pn2); } @@ -606,7 +556,7 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc) * The old name is a use of its pn_lexdef. Make the clone also be a * use of that definition. */ - JSDefinition *dn = pn->pn_lexdef; + Definition *dn = pn->pn_lexdef; pn->pn_link = dn->dn_uses; dn->dn_uses = pn; @@ -619,7 +569,7 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc) */ if (opn->isDefn()) { opn->setDefn(false); - LinkUseToDef(opn, (JSDefinition *) pn, tc); + LinkUseToDef(opn, (Definition *) pn, tc); } } break; @@ -641,8 +591,6 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc) #endif /* JS_HAS_DESTRUCTURING */ -namespace js { - /* * Used by Parser::forStatement and comprehensionTail to clone the TARGET in * for (var/const/let TARGET in EXPR) @@ -653,37 +601,35 @@ namespace js { * The cloned tree is for use only in the same statement and binding context as * the original tree. */ -JSParseNode * -CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc) +ParseNode * +CloneLeftHandSide(ParseNode *opn, TreeContext *tc) { - JSParseNode *pn = NewOrRecycledNode(tc); + ParseNode *pn = tc->parser->new_(opn->getKind(), opn->getOp(), opn->getArity(), + opn->pn_pos); if (!pn) return NULL; - pn->setKind(opn->getKind()); - pn->setOp(opn->getOp()); - pn->setUsed(opn->isUsed()); - pn->setDefn(opn->isDefn()); - pn->setArity(opn->getArity()); pn->setInParens(opn->isInParens()); - pn->pn_pos = opn->pn_pos; + pn->setDefn(opn->isDefn()); + pn->setUsed(opn->isUsed()); #if JS_HAS_DESTRUCTURING if (opn->isArity(PN_LIST)) { JS_ASSERT(opn->isKind(TOK_RB) || opn->isKind(TOK_RC)); pn->makeEmpty(); - for (JSParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) { - JSParseNode *pn2; + for (ParseNode *opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) { + ParseNode *pn2; if (opn->isKind(TOK_RC)) { JS_ASSERT(opn2->isArity(PN_BINARY)); JS_ASSERT(opn2->isKind(TOK_COLON)); - JSParseNode *tag = CloneParseTree(opn2->pn_left, tc); + ParseNode *tag = CloneParseTree(opn2->pn_left, tc); if (!tag) return NULL; - JSParseNode *target = CloneLeftHandSide(opn2->pn_right, tc); + ParseNode *target = CloneLeftHandSide(opn2->pn_right, tc); if (!target) return NULL; - pn2 = BinaryNode::create(TOK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target, tc); + + pn2 = tc->parser->new_(TOK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target); } else if (opn2->isArity(PN_NULLARY)) { JS_ASSERT(opn2->isKind(TOK_COMMA)); pn2 = CloneParseTree(opn2, tc); @@ -707,7 +653,7 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc) pn->pn_u.name = opn->pn_u.name; pn->setOp(JSOP_SETNAME); if (opn->isUsed()) { - JSDefinition *dn = pn->pn_lexdef; + Definition *dn = pn->pn_lexdef; pn->pn_link = dn->dn_uses; dn->dn_uses = pn; @@ -719,7 +665,7 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc) pn->pn_dflags &= ~PND_BOUND; pn->setDefn(false); - LinkUseToDef(pn, (JSDefinition *) opn, tc); + LinkUseToDef(pn, (Definition *) opn, tc); } } return pn; diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 79732fdf2e82..a0f9720603b5 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -46,6 +46,8 @@ #include "frontend/ParseMaps.h" #include "frontend/TokenStream.h" +namespace js { + /* * Parsing builds a tree of nodes that directs code generation. This tree is * not a concrete syntax tree in all respects (for example, || and && are left @@ -57,7 +59,7 @@ * Label Variant Members * ----- ------- ------- * - * TOK_FUNCTION name pn_funbox: ptr to JSFunctionBox holding function + * TOK_FUNCTION name pn_funbox: ptr to js::FunctionBox holding function * object containing arg and var properties. We * create the function object at parse (not emit) * time to specialize arg and var bytecodes early. @@ -74,7 +76,7 @@ * TOK_ARGSBODY list list of formal parameters followed by TOK_LC node * for function body statements as final element * pn_count: 1 + number of formal parameters - * TOK_UPVARS nameset pn_names: lexical dependencies (JSDefinitions) + * TOK_UPVARS nameset pn_names: lexical dependencies (js::Definitions) * defined in enclosing scopes, or ultimately not * defined (free variables, either global property * references or reference errors). @@ -281,7 +283,7 @@ * Label Variant Members * ----- ------- ------- * TOK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR - * pn_objbox: block object in JSObjectBox holder + * pn_objbox: block object in ObjectBox holder * pn_expr: block body * TOK_ARRAYCOMP list pn_count: 1 * pn_head: list of 1 element, which is block @@ -290,7 +292,7 @@ * TOK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP * pn_kid: array comprehension expression */ -typedef enum JSParseNodeArity { +enum ParseNodeArity { PN_NULLARY, /* 0 kids, only pn_atom/pn_dval/etc. */ PN_UNARY, /* one kid, plus a couple of scalars */ PN_BINARY, /* two kids, plus a couple of scalars */ @@ -298,65 +300,85 @@ typedef enum JSParseNodeArity { PN_FUNC, /* function definition node */ PN_LIST, /* generic singly linked list */ PN_NAME, /* name use or definition node */ - PN_NAMESET /* JSAtomDefnMapPtr + JSParseNode ptr */ -} JSParseNodeArity; + PN_NAMESET /* AtomDefnMapPtr + ParseNode ptr */ +}; -struct JSDefinition; +struct Definition; -struct JSParseNode { +struct ParseNode { private: uint32 pn_type : 16, /* TOK_* type, see frontend/TokenStream.h */ pn_op : 8, /* see JSOp enum and jsopcode.tbl */ - pn_arity : 5, /* see JSParseNodeArity enum */ + pn_arity : 5, /* see ParseNodeArity enum */ pn_parens : 1, /* this expr was enclosed in parens */ pn_used : 1, /* name node is on a use-chain */ - pn_defn : 1; /* this node is a JSDefinition */ + pn_defn : 1; /* this node is a Definition */ public: + ParseNode(TokenKind type, JSOp op, ParseNodeArity arity) + : pn_type(type), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0), + pn_offset(0), pn_next(NULL), pn_link(NULL) + { + pn_pos.begin.index = 0; + pn_pos.begin.lineno = 0; + pn_pos.end.index = 0; + pn_pos.end.lineno = 0; + memset(&pn_u, 0, sizeof pn_u); + } + + ParseNode(TokenKind type, JSOp op, ParseNodeArity arity, const TokenPos &pos) + : pn_type(type), pn_op(op), pn_arity(arity), pn_parens(0), pn_used(0), pn_defn(0), + pn_pos(pos), pn_offset(0), pn_next(NULL), pn_link(NULL) + { + memset(&pn_u, 0, sizeof pn_u); + } + JSOp getOp() const { return JSOp(pn_op); } void setOp(JSOp op) { pn_op = op; } bool isOp(JSOp op) const { return getOp() == op; } - js::TokenKind getKind() const { return js::TokenKind(pn_type); } - void setKind(js::TokenKind kind) { pn_type = kind; } - bool isKind(js::TokenKind kind) const { return getKind() == kind; } - JSParseNodeArity getArity() const { return JSParseNodeArity(pn_arity); } - bool isArity(JSParseNodeArity a) const { return getArity() == a; } - void setArity(JSParseNodeArity a) { pn_arity = a; } + TokenKind getKind() const { return TokenKind(pn_type); } + void setKind(TokenKind kind) { pn_type = kind; } + bool isKind(TokenKind kind) const { return getKind() == kind; } + ParseNodeArity getArity() const { return ParseNodeArity(pn_arity); } + bool isArity(ParseNodeArity a) const { return getArity() == a; } + void setArity(ParseNodeArity a) { pn_arity = a; } + /* Boolean attributes. */ bool isInParens() const { return pn_parens; } void setInParens(bool enabled) { pn_parens = enabled; } - bool isDefn() const { return pn_defn; } - void setDefn(bool enabled) { pn_defn = enabled; } bool isUsed() const { return pn_used; } void setUsed(bool enabled) { pn_used = enabled; } + bool isDefn() const { return pn_defn; } + void setDefn(bool enabled) { pn_defn = enabled; } - js::TokenPos pn_pos; /* two 16-bit pairs here, for 64 bits */ + TokenPos pn_pos; /* two 16-bit pairs here, for 64 bits */ int32 pn_offset; /* first generated bytecode offset */ - JSParseNode *pn_next; /* intrinsic link in parent PN_LIST */ - JSParseNode *pn_link; /* def/use link (alignment freebie); - also links JSFunctionBox::methods + ParseNode *pn_next; /* intrinsic link in parent PN_LIST */ + ParseNode *pn_link; /* def/use link (alignment freebie); + also links FunctionBox::methods lists of would-be |this| methods */ + union { struct { /* list of next-linked nodes */ - JSParseNode *head; /* first node in list */ - JSParseNode **tail; /* ptr to ptr to last node in list */ + ParseNode *head; /* first node in list */ + ParseNode **tail; /* ptr to ptr to last node in list */ uint32 count; /* number of nodes in list */ uint32 xflags:12, /* extra flags, see below */ blockid:20; /* see name variant below */ } list; struct { /* ternary: if, for(;;), ?: */ - JSParseNode *kid1; /* condition, discriminant, etc. */ - JSParseNode *kid2; /* then-part, case list, etc. */ - JSParseNode *kid3; /* else-part, default case, etc. */ + ParseNode *kid1; /* condition, discriminant, etc. */ + ParseNode *kid2; /* then-part, case list, etc. */ + ParseNode *kid3; /* else-part, default case, etc. */ } ternary; struct { /* two kids if binary */ - JSParseNode *left; - JSParseNode *right; - js::Value *pval; /* switch case value */ + ParseNode *left; + ParseNode *right; + Value *pval; /* switch case value */ uintN iflags; /* JSITER_* flags for TOK_FOR node */ } binary; struct { /* one kid if unary */ - JSParseNode *kid; + ParseNode *kid; jsint num; /* -1 or sharp variable number */ JSBool hidden; /* hidden genexp-induced JSOP_YIELD or directive prologue member (as @@ -365,15 +387,15 @@ struct JSParseNode { struct { /* name, labeled statement, etc. */ union { JSAtom *atom; /* lexical name or label atom */ - JSFunctionBox *funbox; /* function object */ - JSObjectBox *objbox; /* block or regexp object */ + FunctionBox *funbox; /* function object */ + ObjectBox *objbox; /* block or regexp object */ }; union { - JSParseNode *expr; /* function body, var initializer, or + ParseNode *expr; /* function body, var initializer, or base object of TOK_DOT */ - JSDefinition *lexdef; /* lexical definition for this use */ + Definition *lexdef; /* lexical definition for this use */ }; - js::UpvarCookie cookie; /* upvar cookie with absolute frame + UpvarCookie cookie; /* upvar cookie with absolute frame level (not relative skip), possibly in current frame */ uint32 dflags:12, /* definition/use flags, see below */ @@ -381,11 +403,11 @@ struct JSParseNode { computation */ } name; struct { /* lexical dependencies + sub-tree */ - js::AtomDefnMapPtr defnMap; - JSParseNode *tree; /* sub-tree containing name uses */ + AtomDefnMapPtr defnMap; + ParseNode *tree; /* sub-tree containing name uses */ } nameset; struct { /* PN_NULLARY variant for E4X XML PI */ - js::PropertyName *target; /* target in */ + PropertyName *target; /* target in */ JSAtom *data; /* data (or null) in */ } xmlpi; jsdouble dval; /* aligned numeric literal value */ @@ -422,8 +444,8 @@ struct JSParseNode { #define pn_pitarget pn_u.xmlpi.target #define pn_pidata pn_u.xmlpi.data -protected: - void init(js::TokenKind type, JSOp op, JSParseNodeArity arity) { + protected: + void init(TokenKind type, JSOp op, ParseNodeArity arity) { pn_type = type; pn_op = op; pn_arity = arity; @@ -434,16 +456,11 @@ protected: pn_next = pn_link = NULL; } - static JSParseNode *create(JSParseNodeArity arity, JSTreeContext *tc); - static JSParseNode *create(JSParseNodeArity arity, js::TokenKind type, JSOp op, - const js::TokenPos &pos, JSTreeContext *tc); + static ParseNode *create(ParseNodeArity arity, TreeContext *tc); -public: - static JSParseNode *newBinaryOrAppend(js::TokenKind tt, JSOp op, JSParseNode *left, - JSParseNode *right, JSTreeContext *tc); - - static JSParseNode *newTernary(js::TokenKind tt, JSOp op, JSParseNode *kid1, JSParseNode *kid2, - JSParseNode *kid3, JSTreeContext *tc); + public: + static ParseNode *newBinaryOrAppend(TokenKind tt, JSOp op, ParseNode *left, ParseNode *right, + TreeContext *tc); /* * The pn_expr and lexdef members are arms of an unsafe union. Unless you @@ -451,20 +468,20 @@ public: * them. For less overhead and assertions for protection, use pn->expr() * and pn->lexdef(). Otherwise, use pn->maybeExpr() and pn->maybeLexDef(). */ - JSParseNode *expr() const { + ParseNode *expr() const { JS_ASSERT(!pn_used); JS_ASSERT(pn_arity == PN_NAME || pn_arity == PN_FUNC); return pn_expr; } - JSDefinition *lexdef() const { + Definition *lexdef() const { JS_ASSERT(pn_used || isDeoptimized()); JS_ASSERT(pn_arity == PN_NAME); return pn_lexdef; } - JSParseNode *maybeExpr() { return pn_used ? NULL : expr(); } - JSDefinition *maybeLexDef() { return pn_used ? lexdef() : NULL; } + ParseNode *maybeExpr() { return pn_used ? NULL : expr(); } + Definition *maybeLexDef() { return pn_used ? lexdef() : NULL; } /* PN_FUNC and PN_NAME pn_dflags bits. */ #define PND_LET 0x01 /* let (block-scoped) binding */ @@ -543,17 +560,17 @@ public: */ bool isTopLevel() const { return test(PND_TOPLEVEL); } - /* Defined below, see after struct JSDefinition. */ + /* Defined below, see after struct Definition. */ void setFunArg(); - void become(JSParseNode *pn2); + void become(ParseNode *pn2); void clear(); /* True if pn is a parsenode representing a literal constant. */ bool isLiteral() const { - return isKind(js::TOK_NUMBER) || - isKind(js::TOK_STRING) || - (isKind(js::TOK_PRIMARY) && !isOp(JSOP_THIS)); + return isKind(TOK_NUMBER) || + isKind(TOK_STRING) || + (isKind(TOK_PRIMARY) && !isOp(JSOP_THIS)); } /* @@ -572,10 +589,10 @@ public: * a directive. */ bool isStringExprStatement() const { - if (getKind() == js::TOK_SEMI) { + if (getKind() == TOK_SEMI) { JS_ASSERT(pn_arity == PN_UNARY); - JSParseNode *kid = pn_kid; - return kid && kid->getKind() == js::TOK_STRING && !kid->pn_parens; + ParseNode *kid = pn_kid; + return kid && kid->getKind() == TOK_STRING && !kid->pn_parens; } return false; } @@ -586,7 +603,7 @@ public: * contain escape sequences or line continuations. */ bool isEscapeFreeStringLiteral() const { - JS_ASSERT(pn_type == js::TOK_STRING && !pn_parens); + JS_ASSERT(pn_type == TOK_STRING && !pn_parens); JSString *str = pn_atom; /* @@ -606,26 +623,26 @@ public: * True if this node is a desugared generator expression. */ bool isGeneratorExpr() const { - if (getKind() == js::TOK_LP) { - JSParseNode *callee = this->pn_head; - if (callee->getKind() == js::TOK_FUNCTION) { - JSParseNode *body = (callee->pn_body->getKind() == js::TOK_UPVARS) - ? callee->pn_body->pn_tree - : callee->pn_body; - if (body->getKind() == js::TOK_LEXICALSCOPE) + if (getKind() == TOK_LP) { + ParseNode *callee = this->pn_head; + if (callee->getKind() == TOK_FUNCTION) { + ParseNode *body = (callee->pn_body->getKind() == TOK_UPVARS) + ? callee->pn_body->pn_tree + : callee->pn_body; + if (body->getKind() == TOK_LEXICALSCOPE) return true; } } return false; } - JSParseNode *generatorExpr() const { + ParseNode *generatorExpr() const { JS_ASSERT(isGeneratorExpr()); - JSParseNode *callee = this->pn_head; - JSParseNode *body = callee->pn_body->getKind() == js::TOK_UPVARS - ? callee->pn_body->pn_tree - : callee->pn_body; - JS_ASSERT(body->getKind() == js::TOK_LEXICALSCOPE); + ParseNode *callee = this->pn_head; + ParseNode *body = callee->pn_body->getKind() == TOK_UPVARS + ? callee->pn_body->pn_tree + : callee->pn_body; + JS_ASSERT(body->getKind() == TOK_LEXICALSCOPE); return body->pn_expr; } #endif @@ -634,10 +651,10 @@ public: * Compute a pointer to the last element in a singly-linked list. NB: list * must be non-empty for correct PN_LAST usage -- this is asserted! */ - JSParseNode *last() const { + ParseNode *last() const { JS_ASSERT(pn_arity == PN_LIST); JS_ASSERT(pn_count != 0); - return (JSParseNode *)(uintptr_t(pn_tail) - offsetof(JSParseNode, pn_next)); + return (ParseNode *)(uintptr_t(pn_tail) - offsetof(ParseNode, pn_next)); } void makeEmpty() { @@ -649,7 +666,7 @@ public: pn_blockid = 0; } - void initList(JSParseNode *pn) { + void initList(ParseNode *pn) { JS_ASSERT(pn_arity == PN_LIST); pn_head = pn; pn_tail = &pn->pn_next; @@ -658,122 +675,110 @@ public: pn_blockid = 0; } - void append(JSParseNode *pn) { + void append(ParseNode *pn) { JS_ASSERT(pn_arity == PN_LIST); *pn_tail = pn; pn_tail = &pn->pn_next; pn_count++; } - bool getConstantValue(JSContext *cx, bool strictChecks, js::Value *vp); + bool getConstantValue(JSContext *cx, bool strictChecks, Value *vp); inline bool isConstant(); }; -namespace js { - -struct NullaryNode : public JSParseNode { - static inline NullaryNode *create(JSTreeContext *tc) { - return (NullaryNode *)JSParseNode::create(PN_NULLARY, tc); +struct NullaryNode : public ParseNode { + static inline NullaryNode *create(TreeContext *tc) { + return (NullaryNode *)ParseNode::create(PN_NULLARY, tc); } }; -struct UnaryNode : public JSParseNode { - static inline UnaryNode *create(JSTreeContext *tc) { - return (UnaryNode *)JSParseNode::create(PN_UNARY, tc); +struct UnaryNode : public ParseNode { + UnaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *kid) + : ParseNode(type, op, PN_UNARY, pos) + { + pn_kid = kid; + } + + static inline UnaryNode *create(TreeContext *tc) { + return (UnaryNode *)ParseNode::create(PN_UNARY, tc); } }; -struct BinaryNode : public JSParseNode { - static inline BinaryNode *create(TokenKind type, JSOp op, const TokenPos &pos, - JSParseNode *left, JSParseNode *right, - JSTreeContext *tc) { - BinaryNode *pn = (BinaryNode *) JSParseNode::create(PN_BINARY, type, op, pos, tc); - if (pn) { - pn->pn_left = left; - pn->pn_right = right; - } - return pn; +struct BinaryNode : public ParseNode { + BinaryNode(TokenKind type, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right) + : ParseNode(type, op, PN_BINARY, pos) + { + pn_left = left; + pn_right = right; } - static inline BinaryNode *create(JSTreeContext *tc) { - return (BinaryNode *)JSParseNode::create(PN_BINARY, tc); + BinaryNode(TokenKind type, JSOp op, ParseNode *left, ParseNode *right) + : ParseNode(type, op, PN_BINARY, TokenPos::box(left->pn_pos, right->pn_pos)) + { + pn_left = left; + pn_right = right; + } + + static inline BinaryNode *create(TreeContext *tc) { + return (BinaryNode *)ParseNode::create(PN_BINARY, tc); } }; -struct TernaryNode : public JSParseNode { - static inline TernaryNode *create(TokenKind type, JSOp op, - JSParseNode *kid1, JSParseNode *kid2, JSParseNode *kid3, - JSTreeContext *tc) { - TokenPos pos; - pos.begin = (kid1 ? kid1 : kid2)->pn_pos.begin; - pos.end = kid3->pn_pos.end; - TernaryNode *pn = (TernaryNode *) JSParseNode::create(PN_TERNARY, type, op, pos, tc); - if (pn) { - pn->pn_kid1 = kid1; - pn->pn_kid2 = kid2; - pn->pn_kid3 = kid3; - } - return pn; +struct TernaryNode : public ParseNode { + TernaryNode(TokenKind type, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3) + : ParseNode(type, op, PN_TERNARY, + TokenPos((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin, + (kid3 ? kid3 : kid2 ? kid2 : kid1)->pn_pos.end)) + { + pn_kid1 = kid1; + pn_kid2 = kid2; + pn_kid3 = kid3; } - static inline TernaryNode *create(JSTreeContext *tc) { - return (TernaryNode *)JSParseNode::create(PN_TERNARY, tc); + static inline TernaryNode *create(TreeContext *tc) { + return (TernaryNode *)ParseNode::create(PN_TERNARY, tc); } }; -struct ListNode : public JSParseNode { - static inline ListNode *create(JSTreeContext *tc) { - return (ListNode *)JSParseNode::create(PN_LIST, tc); +struct ListNode : public ParseNode { + static inline ListNode *create(TreeContext *tc) { + return (ListNode *)ParseNode::create(PN_LIST, tc); } }; -struct FunctionNode : public JSParseNode { - static inline FunctionNode *create(JSTreeContext *tc) { - return (FunctionNode *)JSParseNode::create(PN_FUNC, tc); +struct FunctionNode : public ParseNode { + static inline FunctionNode *create(TreeContext *tc) { + return (FunctionNode *)ParseNode::create(PN_FUNC, tc); } }; -struct NameNode : public JSParseNode { - static NameNode *create(JSAtom *atom, JSTreeContext *tc); +struct NameNode : public ParseNode { + static NameNode *create(JSAtom *atom, TreeContext *tc); - void inline initCommon(JSTreeContext *tc); + inline void initCommon(TreeContext *tc); }; -struct NameSetNode : public JSParseNode { - static inline NameSetNode *create(JSTreeContext *tc) { - return (NameSetNode *)JSParseNode::create(PN_NAMESET, tc); +struct NameSetNode : public ParseNode { + static inline NameSetNode *create(TreeContext *tc) { + return (NameSetNode *)ParseNode::create(PN_NAMESET, tc); } }; -struct LexicalScopeNode : public JSParseNode { - static inline LexicalScopeNode *create(JSTreeContext *tc) { - return (LexicalScopeNode *)JSParseNode::create(PN_NAME, tc); +struct LexicalScopeNode : public ParseNode { + static inline LexicalScopeNode *create(TreeContext *tc) { + return (LexicalScopeNode *)ParseNode::create(PN_NAME, tc); } }; -JSParseNode * -NewOrRecycledNode(JSTreeContext *tc); - -void -AddNodeToFreeList(JSParseNode *pn, Parser *parser); - -void -PrepareNodeForMutation(JSParseNode *pn, JSTreeContext *tc); - -JSParseNode * -RecycleTree(JSParseNode *pn, JSTreeContext *tc); - -JSParseNode * -CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc); - -} /* namespace js */ +ParseNode * +CloneLeftHandSide(ParseNode *opn, TreeContext *tc); /* - * JSDefinition is a degenerate subtype of the PN_FUNC and PN_NAME variants of - * JSParseNode, allocated only for function, var, const, and let declarations - * that define truly lexical bindings. This means that a child of a TOK_VAR - * list may be a JSDefinition instead of a JSParseNode. The pn_defn bit is set - * for all JSDefinitions, clear otherwise. + * js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants + * of js::ParseNode, allocated only for function, var, const, and let + * declarations that define truly lexical bindings. This means that a child of + * a TOK_VAR list may be a Definition instead of a ParseNode. The pn_defn + * bit is set for all Definitions, clear otherwise. * * In an upvars list, defn->resolve() is the outermost definition the * name may reference. If a with block or a function that calls eval encloses @@ -806,24 +811,24 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc); * for (each use of unqualified name x in parse order) { * if (this use of x is a declaration) { * if (x in tc->decls) { // redeclaring - * pn = allocate a PN_NAME JSParseNode; + * pn = allocate a PN_NAME ParseNode; * } else { // defining * dn = lookup x in tc->lexdeps; * if (dn) // use before def * remove x from tc->lexdeps; * else // def before use - * dn = allocate a PN_NAME JSDefinition; + * dn = allocate a PN_NAME Definition; * map x to dn via tc->decls; * pn = dn; * } * insert pn into its parent TOK_VAR list; * } else { - * pn = allocate a JSParseNode for this reference to x; + * pn = allocate a ParseNode for this reference to x; * dn = lookup x in tc's lexical scope chain; * if (!dn) { * dn = lookup x in tc->lexdeps; * if (!dn) { - * dn = pre-allocate a JSDefinition for x; + * dn = pre-allocate a Definition for x; * map x to dn in tc->lexdeps; * } * } @@ -831,13 +836,13 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc); * } * } * - * See frontend/BytecodeGenerator.h for JSTreeContext and its top*Stmt, decls, and - * lexdeps members. + * See frontend/BytecodeGenerator.h for js::TreeContext and its top*Stmt, + * decls, and lexdeps members. * * Notes: * - * 0. To avoid bloating JSParseNode, we steal a bit from pn_arity for pn_defn - * and set it on a JSParseNode instead of allocating a JSDefinition. + * 0. To avoid bloating ParseNode, we steal a bit from pn_arity for pn_defn + * and set it on a ParseNode instead of allocating a Definition. * * 1. Due to hoisting, a definition cannot be eliminated even if its "Variable * statement" (ECMA-262 12.2) can be proven to be dead code. RecycleTree in @@ -888,10 +893,10 @@ CloneLeftHandSide(JSParseNode *opn, JSTreeContext *tc); */ #define dn_uses pn_link -struct JSDefinition : public JSParseNode +struct Definition : public ParseNode { /* - * We store definition pointers in PN_NAMESET JSAtomDefnMapPtrs in the AST, + * We store definition pointers in PN_NAMESET AtomDefnMapPtrs in the AST, * but due to redefinition these nodes may become uses of other * definitions. This is unusual, so we simply chase the pn_lexdef link to * find the final definition node. See methods called from @@ -899,16 +904,16 @@ struct JSDefinition : public JSParseNode * * FIXME: MakeAssignment mutates for want of a parent link... */ - JSDefinition *resolve() { - JSParseNode *pn = this; + Definition *resolve() { + ParseNode *pn = this; while (!pn->isDefn()) { - if (pn->getKind() == js::TOK_ASSIGN) { + if (pn->getKind() == TOK_ASSIGN) { pn = pn->pn_left; continue; } pn = pn->lexdef(); } - return (JSDefinition *) pn; + return (Definition *) pn; } bool isFreeVar() const { @@ -928,9 +933,9 @@ struct JSDefinition : public JSParseNode static const char *kindString(Kind kind); Kind kind() { - if (getKind() == js::TOK_FUNCTION) + if (getKind() == TOK_FUNCTION) return FUNCTION; - JS_ASSERT(getKind() == js::TOK_NAME); + JS_ASSERT(getKind() == TOK_NAME); if (isOp(JSOP_NOP)) return UNKNOWN; if (isOp(JSOP_GETARG)) @@ -943,13 +948,27 @@ struct JSDefinition : public JSParseNode } }; +class ParseNodeAllocator { + public: + explicit ParseNodeAllocator(JSContext *cx) : cx(cx), freelist(NULL) {} + + void *allocNode(); + void freeNode(ParseNode *pn); + ParseNode *freeTree(ParseNode *pn); + void prepareNodeForMutation(ParseNode *pn); + + private: + JSContext *cx; + ParseNode *freelist; +}; + inline bool -JSParseNode::test(uintN flag) const +ParseNode::test(uintN flag) const { JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME); #ifdef DEBUG if ((flag & (PND_ASSIGNED | PND_FUNARG)) && pn_defn && !(pn_dflags & flag)) { - for (JSParseNode *pn = ((JSDefinition *) this)->dn_uses; pn; pn = pn->pn_link) { + for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) { JS_ASSERT(!pn->pn_defn); JS_ASSERT(!(pn->pn_dflags & flag)); } @@ -959,7 +978,7 @@ JSParseNode::test(uintN flag) const } inline void -JSParseNode::setFunArg() +ParseNode::setFunArg() { /* * pn_defn NAND pn_used must be true, per this chart: @@ -977,10 +996,8 @@ JSParseNode::setFunArg() pn_dflags |= PND_FUNARG; } -namespace js { - inline void -LinkUseToDef(JSParseNode *pn, JSDefinition *dn, JSTreeContext *tc) +LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc) { JS_ASSERT(!pn->isUsed()); JS_ASSERT(!pn->isDefn()); @@ -992,31 +1009,29 @@ LinkUseToDef(JSParseNode *pn, JSDefinition *dn, JSTreeContext *tc) pn->pn_lexdef = dn; } -} /* namespace js */ - -struct JSObjectBox { - JSObjectBox *traceLink; - JSObjectBox *emitLink; +struct ObjectBox { + ObjectBox *traceLink; + ObjectBox *emitLink; JSObject *object; - JSObjectBox *parent; + ObjectBox *parent; uintN index; bool isFunctionBox; }; #define JSFB_LEVEL_BITS 14 -struct JSFunctionBox : public JSObjectBox +struct FunctionBox : public ObjectBox { - JSParseNode *node; - JSFunctionBox *siblings; - JSFunctionBox *kids; - JSFunctionBox *parent; - JSParseNode *methods; /* would-be methods set on this; + ParseNode *node; + FunctionBox *siblings; + FunctionBox *kids; + FunctionBox *parent; + ParseNode *methods; /* would-be methods set on this; these nodes are linked via pn_link, since lambdas are neither definitions nor uses of a binding */ - js::Bindings bindings; /* bindings for this function */ + Bindings bindings; /* bindings for this function */ uint32 queued:1, inLoop:1, /* in a loop in parent function */ level:JSFB_LEVEL_BITS; @@ -1051,26 +1066,26 @@ struct JSFunctionBox : public JSObjectBox bool shouldUnbrand(uintN methods, uintN slowMethods) const; }; -struct JSFunctionBoxQueue { - JSFunctionBox **vector; +struct FunctionBoxQueue { + FunctionBox **vector; size_t head, tail; size_t lengthMask; size_t count() { return head - tail; } size_t length() { return lengthMask + 1; } - JSFunctionBoxQueue() + FunctionBoxQueue() : vector(NULL), head(0), tail(0), lengthMask(0) { } bool init(uint32 count) { lengthMask = JS_BITMASK(JS_CEILING_LOG2W(count)); - vector = (JSFunctionBox **) js::OffTheBooks::malloc_(sizeof(JSFunctionBox) * length()); + vector = (FunctionBox **) OffTheBooks::malloc_(sizeof(FunctionBox) * length()); return !!vector; } - ~JSFunctionBoxQueue() { js::UnwantedForeground::free_(vector); } + ~FunctionBoxQueue() { UnwantedForeground::free_(vector); } - void push(JSFunctionBox *funbox) { + void push(FunctionBox *funbox) { if (!funbox->queued) { JS_ASSERT(count() < length()); vector[head++ & lengthMask] = funbox; @@ -1078,14 +1093,16 @@ struct JSFunctionBoxQueue { } } - JSFunctionBox *pull() { + FunctionBox *pull() { if (tail == head) return NULL; JS_ASSERT(tail < head); - JSFunctionBox *funbox = vector[tail++ & lengthMask]; + FunctionBox *funbox = vector[tail++ & lengthMask]; funbox->queued = false; return funbox; } }; +} /* namespace js */ + #endif /* ParseNode_h__ */ diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index c9f304b821e6..bc02722da57c 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -44,10 +44,10 @@ * This is a recursive-descent parser for the JavaScript language specified by * "The JavaScript 1.5 Language Specification". It uses lexical and semantic * feedback to disambiguate non-LL(1) structures. It generates trees of nodes - * induced by the recursive parsing (not precise syntax trees, see jsparse.h). + * induced by the recursive parsing (not precise syntax trees, see Parser.h). * After tree construction, it rewrites trees to fold constants and evaluate - * compile-time expressions. Finally, it calls js_EmitTree (see jsemit.h) to - * generate bytecode. + * compile-time expressions. Finally, it calls js::frontend::EmitTree (see + * CodeGenerator.h) to generate bytecode. * * This parser attempts no error recovery. */ @@ -101,6 +101,7 @@ using namespace js; using namespace js::gc; +using namespace js::frontend; /* * Insist that the next token be of type tt, or report errno and return null. @@ -116,13 +117,13 @@ using namespace js::gc; #define MUST_MATCH_TOKEN(tt, errno) MUST_MATCH_TOKEN_WITH_FLAGS(tt, errno, 0) Parser::Parser(JSContext *cx, JSPrincipals *prin, StackFrame *cfp, bool foldConstants) - : js::AutoGCRooter(cx, PARSER), + : AutoGCRooter(cx, PARSER), context(cx), tokenStream(cx), principals(NULL), callerFrame(cfp), callerVarObj(cfp ? &cfp->varObj() : NULL), - nodeList(NULL), + allocator(cx), functionCount(0), traceListHead(NULL), tc(NULL), @@ -130,7 +131,7 @@ Parser::Parser(JSContext *cx, JSPrincipals *prin, StackFrame *cfp, bool foldCons foldConstants(foldConstants) { cx->activeCompilations++; - js::PodArrayZero(tempFreeList); + PodArrayZero(tempFreeList); setPrincipals(prin); JS_ASSERT_IF(cfp, cfp->isScriptFrame()); } @@ -169,7 +170,7 @@ Parser::setPrincipals(JSPrincipals *prin) principals = prin; } -JSObjectBox * +ObjectBox * Parser::newObjectBox(JSObject *obj) { JS_ASSERT(obj); @@ -180,7 +181,7 @@ Parser::newObjectBox(JSObject *obj) * containing the entries must be alive until we are done with scanning, * parsing and code generation for the whole script or top-level function. */ - JSObjectBox *objbox = context->tempLifoAlloc().new_(); + ObjectBox *objbox = context->tempLifoAlloc().new_(); if (!objbox) { js_ReportOutOfMemory(context); return NULL; @@ -193,8 +194,8 @@ Parser::newObjectBox(JSObject *obj) return objbox; } -JSFunctionBox * -Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc) +FunctionBox * +Parser::newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc) { JS_ASSERT(obj); JS_ASSERT(obj->isFunction()); @@ -205,7 +206,7 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc) * containing the entries must be alive until we are done with scanning, * parsing and code generation for the whole script or top-level function. */ - JSFunctionBox *funbox = context->tempLifoAlloc().newPod(); + FunctionBox *funbox = context->tempLifoAlloc().newPod(); if (!funbox) { js_ReportOutOfMemory(context); return NULL; @@ -225,7 +226,7 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc) new (&funbox->bindings) Bindings(context); funbox->queued = false; funbox->inLoop = false; - for (JSStmtInfo *stmt = tc->topStmt; stmt; stmt = stmt->down) { + for (StmtInfo *stmt = tc->topStmt; stmt; stmt = stmt->down) { if (STMT_IS_LOOP(stmt)) { funbox->inLoop = true; break; @@ -241,15 +242,15 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc) void Parser::trace(JSTracer *trc) { - JSObjectBox *objbox = traceListHead; + ObjectBox *objbox = traceListHead; while (objbox) { MarkObject(trc, *objbox->object, "parser.object"); if (objbox->isFunctionBox) - static_cast(objbox)->bindings.trace(trc); + static_cast(objbox)->bindings.trace(trc); objbox = objbox->traceLink; } - for (JSTreeContext *tc = this->tc; tc; tc = tc->parent) + for (TreeContext *tc = this->tc; tc; tc = tc->parent) tc->trace(trc); } @@ -278,15 +279,15 @@ Parser::trace(JSTracer *trc) * function box tree; it could later be recycled, reallocated, and turned * into anything at all. (Fortunately, method list members never get * mutated, so we don't have to worry about that case.) - * PrepareNodeForMutation clears the node's function box's node pointer, - * disconnecting it entirely from the function box tree, and marking the - * function box to be trimmed out. + * ParseNodeAllocator::prepareNodeForMutation clears the node's function + * box's node pointer, disconnecting it entirely from the function box tree, + * and marking the function box to be trimmed out. */ void -Parser::cleanFunctionList(JSFunctionBox **funboxHead) +Parser::cleanFunctionList(FunctionBox **funboxHead) { - JSFunctionBox **link = funboxHead; - while (JSFunctionBox *box = *link) { + FunctionBox **link = funboxHead; + while (FunctionBox *box = *link) { if (!box->node) { /* * This funbox's parse node was mutated into something else. Drop the box, @@ -299,14 +300,14 @@ Parser::cleanFunctionList(JSFunctionBox **funboxHead) * the node, and stay at the same link. */ *link = box->siblings; - AddNodeToFreeList(box->node, this); + allocator.freeNode(box->node); } else { /* The function is still live. */ /* First, remove nodes for deleted functions from our methods list. */ { - JSParseNode **methodLink = &box->methods; - while (JSParseNode *method = *methodLink) { + ParseNode **methodLink = &box->methods; + while (ParseNode *method = *methodLink) { /* Method nodes are never rewritten in place to be other kinds of nodes. */ JS_ASSERT(method->isArity(PN_FUNC)); if (!method->pn_funbox) { @@ -329,7 +330,7 @@ Parser::cleanFunctionList(JSFunctionBox **funboxHead) } static bool -GenerateBlockIdForStmtNode(JSParseNode *pn, JSTreeContext *tc) +GenerateBlockIdForStmtNode(ParseNode *pn, TreeContext *tc) { JS_ASSERT(tc->topStmt); JS_ASSERT(STMT_MAYBE_SCOPE(tc->topStmt)); @@ -343,7 +344,7 @@ GenerateBlockIdForStmtNode(JSParseNode *pn, JSTreeContext *tc) /* * Parse a top-level JS script. */ -JSParseNode * +ParseNode * Parser::parse(JSObject *chain) { /* @@ -354,20 +355,20 @@ Parser::parse(JSObject *chain) * an object lock before it finishes generating bytecode into a script * protected from the GC by a root or a stack frame reference. */ - JSTreeContext globaltc(this); + TreeContext globaltc(this); if (!globaltc.init(context)) return NULL; globaltc.setScopeChain(chain); if (!GenerateBlockId(&globaltc, globaltc.bodyid)) return NULL; - JSParseNode *pn = statements(); + ParseNode *pn = statements(); if (pn) { if (!tokenStream.matchToken(TOK_EOF)) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_SYNTAX_ERROR); pn = NULL; } else if (foldConstants) { - if (!js_FoldConstants(context, pn, &globaltc)) + if (!FoldConstants(context, pn, &globaltc)) pn = NULL; } } @@ -387,9 +388,9 @@ JS_STATIC_ASSERT(UpvarCookie::FREE_LEVEL == JS_BITMASK(JSFB_LEVEL_BITS)); #define ENDS_IN_BREAK 2 static int -HasFinalReturn(JSParseNode *pn) +HasFinalReturn(ParseNode *pn) { - JSParseNode *pn2, *pn3; + ParseNode *pn2, *pn3; uintN rv, rv2, hasDefault; switch (pn->getKind()) { @@ -504,7 +505,7 @@ HasFinalReturn(JSParseNode *pn) } static JSBool -ReportBadReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, uintN flags, uintN errnum, +ReportBadReturn(JSContext *cx, TreeContext *tc, ParseNode *pn, uintN flags, uintN errnum, uintN anonerrnum) { JSAutoByteString name; @@ -518,7 +519,7 @@ ReportBadReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, uintN flags, } static JSBool -CheckFinalReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn) +CheckFinalReturn(JSContext *cx, TreeContext *tc, ParseNode *pn) { JS_ASSERT(tc->inFunction()); return HasFinalReturn(pn) == ENDS_IN_RETURN || @@ -531,7 +532,7 @@ CheckFinalReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn) * assign to 'eval' or 'arguments'. */ static bool -CheckStrictAssignment(JSContext *cx, JSTreeContext *tc, JSParseNode *lhs) +CheckStrictAssignment(JSContext *cx, TreeContext *tc, ParseNode *lhs) { if (tc->needStrictChecks() && lhs->isKind(TOK_NAME)) { JSAtom *atom = lhs->pn_atom; @@ -555,7 +556,7 @@ CheckStrictAssignment(JSContext *cx, JSTreeContext *tc, JSParseNode *lhs) * tc's token stream if pn is NULL. */ bool -CheckStrictBinding(JSContext *cx, JSTreeContext *tc, PropertyName *name, JSParseNode *pn) +CheckStrictBinding(JSContext *cx, TreeContext *tc, PropertyName *name, ParseNode *pn) { if (!tc->needStrictChecks()) return true; @@ -575,9 +576,9 @@ CheckStrictBinding(JSContext *cx, JSTreeContext *tc, PropertyName *name, JSParse } static bool -ReportBadParameter(JSContext *cx, JSTreeContext *tc, JSAtom *name, uintN errorNumber) +ReportBadParameter(JSContext *cx, TreeContext *tc, JSAtom *name, uintN errorNumber) { - JSDefinition *dn = tc->decls.lookupFirst(name); + Definition *dn = tc->decls.lookupFirst(name); JSAutoByteString bytes; return js_AtomToPrintableString(cx, name, &bytes) && ReportStrictModeError(cx, TS(tc->parser), tc, dn, errorNumber, bytes.ptr()); @@ -592,7 +593,7 @@ namespace js { * function's body may turn on strict mode for the function head. */ bool -CheckStrictParameters(JSContext *cx, JSTreeContext *tc) +CheckStrictParameters(JSContext *cx, TreeContext *tc) { JS_ASSERT(tc->inFunction()); @@ -648,19 +649,19 @@ CheckStrictParameters(JSContext *cx, JSTreeContext *tc) } /* namespace js */ -JSParseNode * +ParseNode * Parser::functionBody() { JS_ASSERT(tc->inFunction()); - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_BLOCK, -1); stmtInfo.flags = SIF_BODY_BLOCK; uintN oldflags = tc->flags; tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID); - JSParseNode *pn; + ParseNode *pn; #if JS_HAS_EXPR_CLOSURES if (tokenStream.currentToken().type == TOK_LC) { pn = statements(); @@ -690,7 +691,7 @@ Parser::functionBody() if (pn) { JS_ASSERT(!(tc->topStmt->flags & SIF_SCOPE)); - js_PopStatement(tc); + PopStatementTC(tc); /* Check for falling off the end of a function that returns a value. */ if (context->hasStrictOption() && (tc->flags & TCF_RETURN_EXPR) && @@ -703,11 +704,11 @@ Parser::functionBody() return pn; } -/* Create a placeholder JSDefinition node for |atom|. */ -static JSDefinition * -MakePlaceholder(JSParseNode *pn, JSTreeContext *tc) +/* Create a placeholder Definition node for |atom|. */ +static Definition * +MakePlaceholder(ParseNode *pn, TreeContext *tc) { - JSDefinition *dn = (JSDefinition *) NameNode::create(pn->pn_atom, tc); + Definition *dn = (Definition *) NameNode::create(pn->pn_atom, tc); if (!dn) return NULL; @@ -719,13 +720,13 @@ MakePlaceholder(JSParseNode *pn, JSTreeContext *tc) } static bool -Define(JSParseNode *pn, JSAtom *atom, JSTreeContext *tc, bool let = false) +Define(ParseNode *pn, JSAtom *atom, TreeContext *tc, bool let = false) { JS_ASSERT(!pn->isUsed()); JS_ASSERT_IF(pn->isDefn(), pn->isPlaceholder()); bool foundLexdep = false; - JSDefinition *dn = NULL; + Definition *dn = NULL; if (let) dn = tc->decls.lookupFirst(atom); @@ -736,13 +737,13 @@ Define(JSParseNode *pn, JSAtom *atom, JSTreeContext *tc, bool let = false) } if (dn && dn != pn) { - JSParseNode **pnup = &dn->dn_uses; - JSParseNode *pnu; + ParseNode **pnup = &dn->dn_uses; + ParseNode *pnu; uintN start = let ? pn->pn_blockid : tc->bodyid; while ((pnu = *pnup) != NULL && pnu->pn_blockid >= start) { JS_ASSERT(pnu->isUsed()); - pnu->pn_lexdef = (JSDefinition *) pn; + pnu->pn_lexdef = (Definition *) pn; pn->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS; pnup = &pnu->pn_link; } @@ -757,7 +758,7 @@ Define(JSParseNode *pn, JSAtom *atom, JSTreeContext *tc, bool let = false) } } - JSDefinition *toAdd = (JSDefinition *) pn; + Definition *toAdd = (Definition *) pn; bool ok = let ? tc->decls.addShadow(atom, toAdd) : tc->decls.addUnique(atom, toAdd); if (!ok) return false; @@ -769,32 +770,31 @@ Define(JSParseNode *pn, JSAtom *atom, JSTreeContext *tc, bool let = false) } static void -ForgetUse(JSParseNode *pn) +ForgetUse(ParseNode *pn) { if (!pn->isUsed()) { JS_ASSERT(!pn->isDefn()); return; } - JSParseNode **pnup = &pn->lexdef()->dn_uses; - JSParseNode *pnu; + ParseNode **pnup = &pn->lexdef()->dn_uses; + ParseNode *pnu; while ((pnu = *pnup) != pn) pnup = &pnu->pn_link; *pnup = pn->pn_link; pn->setUsed(false); } -static JSParseNode * -MakeAssignment(JSParseNode *pn, JSParseNode *rhs, JSTreeContext *tc) +static ParseNode * +MakeAssignment(ParseNode *pn, ParseNode *rhs, TreeContext *tc) { - JSParseNode *lhs = NewOrRecycledNode(tc); + ParseNode *lhs = tc->parser->new_(*pn); if (!lhs) return NULL; - *lhs = *pn; if (pn->isUsed()) { - JSDefinition *dn = pn->pn_lexdef; - JSParseNode **pnup = &dn->dn_uses; + Definition *dn = pn->pn_lexdef; + ParseNode **pnup = &dn->dn_uses; while (*pnup != pn) pnup = &(*pnup)->pn_link; @@ -814,8 +814,8 @@ MakeAssignment(JSParseNode *pn, JSParseNode *rhs, JSTreeContext *tc) return lhs; } -static JSParseNode * -MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *tc) +static ParseNode * +MakeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom, TreeContext *tc) { /* * If dn is arg, or in [var, const, let] and has an initializer, then we @@ -823,19 +823,19 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t * left-hand side becomes a use of pn. */ if (dn->isBindingForm()) { - JSParseNode *rhs = dn->expr(); + ParseNode *rhs = dn->expr(); if (rhs) { - JSParseNode *lhs = MakeAssignment(dn, rhs, tc); + ParseNode *lhs = MakeAssignment(dn, rhs, tc); if (!lhs) return NULL; //pn->dn_uses = lhs; - dn = (JSDefinition *) lhs; + dn = (Definition *) lhs; } dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_NAME); - } else if (dn->kind() == JSDefinition::FUNCTION) { + } else if (dn->kind() == Definition::FUNCTION) { JS_ASSERT(dn->isOp(JSOP_NOP)); - PrepareNodeForMutation(dn, tc); + tc->parser->prepareNodeForMutation(dn); dn->setKind(TOK_NAME); dn->setArity(PN_NAME); dn->pn_atom = atom; @@ -846,10 +846,10 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t JS_ASSERT(dn->isArity(PN_NAME)); JS_ASSERT(dn->pn_atom == atom); - for (JSParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { + for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { JS_ASSERT(pnu->isUsed()); JS_ASSERT(!pnu->isDefn()); - pnu->pn_lexdef = (JSDefinition *) pn; + pnu->pn_lexdef = (Definition *) pn; pn->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS; } pn->pn_dflags |= dn->pn_dflags & PND_USE2DEF_FLAGS; @@ -857,7 +857,7 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t dn->setDefn(false); dn->setUsed(true); - dn->pn_lexdef = (JSDefinition *) pn; + dn->pn_lexdef = (Definition *) pn; dn->pn_cookie.makeFree(); dn->pn_dflags &= ~PND_BOUND; return dn; @@ -866,9 +866,9 @@ MakeDefIntoUse(JSDefinition *dn, JSParseNode *pn, JSAtom *atom, JSTreeContext *t namespace js { bool -DefineArg(JSParseNode *pn, JSAtom *atom, uintN i, JSTreeContext *tc) +DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc) { - JSParseNode *argpn, *argsbody; + ParseNode *argpn, *argsbody; /* Flag tc so we don't have to lookup arguments on every use. */ if (atom == tc->parser->context->runtime->atomState.argumentsAtom) @@ -917,12 +917,12 @@ DefineArg(JSParseNode *pn, JSAtom *atom, uintN i, JSTreeContext *tc) * of CheckDestructuring and its friends. */ typedef JSBool -(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc); +(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc); struct BindData { BindData() : fresh(true) {} - JSParseNode *pn; /* name node for definition processing and + ParseNode *pn; /* name node for definition processing and error source coordinates */ JSOp op; /* prolog bytecode or nop */ Binder binder; /* binder, discriminates u */ @@ -935,7 +935,7 @@ struct BindData { }; static bool -BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, BindingKind kind) +BindLocalVariable(JSContext *cx, TreeContext *tc, ParseNode *pn, BindingKind kind) { JS_ASSERT(kind == VARIABLE || kind == CONSTANT); @@ -953,7 +953,7 @@ BindLocalVariable(JSContext *cx, JSTreeContext *tc, JSParseNode *pn, BindingKind #if JS_HAS_DESTRUCTURING static JSBool -BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) +BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc) { /* Flag tc so we don't have to lookup arguments on every use. */ if (atom == tc->parser->context->runtime->atomState.argumentsAtom) @@ -972,7 +972,7 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext return JS_FALSE; } - JSParseNode *pn = data->pn; + ParseNode *pn = data->pn; /* * Distinguish destructured-to binding nodes as vars, not args, by setting @@ -1001,7 +1001,7 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext #endif /* JS_HAS_DESTRUCTURING */ JSFunction * -Parser::newFunction(JSTreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind) +Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind) { JS_ASSERT_IF(kind == Statement, atom != NULL); @@ -1043,7 +1043,7 @@ MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts) } bool -Parser::analyzeFunctions(JSTreeContext *tc) +Parser::analyzeFunctions(TreeContext *tc) { cleanFunctionList(&tc->functionList); if (!tc->functionList) @@ -1086,12 +1086,12 @@ Parser::analyzeFunctions(JSTreeContext *tc) * FREE_STATIC_LEVEL. Thus this function never returns 0. */ static uintN -FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue) +FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue) { uintN allskipmin = UpvarCookie::FREE_LEVEL; do { - JSParseNode *fn = funbox->node; + ParseNode *fn = funbox->node; JS_ASSERT(fn->isArity(PN_FUNC)); JSFunction *fun = funbox->function(); int fnlevel = level; @@ -1112,7 +1112,7 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue) */ if (funbox->tcflags & (TCF_FUN_HEAVYWEIGHT | TCF_FUN_IS_GENERATOR)) { fn->setFunArg(); - for (JSFunctionBox *kid = funbox->kids; kid; kid = kid->siblings) + for (FunctionBox *kid = funbox->kids; kid; kid = kid->siblings) kid->node->setFunArg(); } @@ -1122,15 +1122,15 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue) * nested in fun. */ uintN skipmin = UpvarCookie::FREE_LEVEL; - JSParseNode *pn = fn->pn_body; + ParseNode *pn = fn->pn_body; if (pn->isKind(TOK_UPVARS)) { AtomDefnMapPtr &upvars = pn->pn_names; JS_ASSERT(upvars->count() != 0); for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - JSDefinition *defn = r.front().value(); - JSDefinition *lexdep = defn->resolve(); + Definition *defn = r.front().value(); + Definition *lexdep = defn->resolve(); if (!lexdep->isFreeVar()) { uintN upvarLevel = lexdep->frameLevel(); @@ -1189,9 +1189,9 @@ FindFunArgs(JSFunctionBox *funbox, int level, JSFunctionBoxQueue *queue) } bool -Parser::markFunArgs(JSFunctionBox *funbox) +Parser::markFunArgs(FunctionBox *funbox) { - JSFunctionBoxQueue queue; + FunctionBoxQueue queue; if (!queue.init(functionCount)) { js_ReportOutOfMemory(context); return false; @@ -1199,21 +1199,21 @@ Parser::markFunArgs(JSFunctionBox *funbox) FindFunArgs(funbox, -1, &queue); while ((funbox = queue.pull()) != NULL) { - JSParseNode *fn = funbox->node; + ParseNode *fn = funbox->node; JS_ASSERT(fn->isFunArg()); - JSParseNode *pn = fn->pn_body; + ParseNode *pn = fn->pn_body; if (pn->isKind(TOK_UPVARS)) { AtomDefnMapPtr upvars = pn->pn_names; JS_ASSERT(!upvars->empty()); for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - JSDefinition *defn = r.front().value(); - JSDefinition *lexdep = defn->resolve(); + Definition *defn = r.front().value(); + Definition *lexdep = defn->resolve(); if (!lexdep->isFreeVar() && !lexdep->isFunArg() && - (lexdep->kind() == JSDefinition::FUNCTION || + (lexdep->kind() == Definition::FUNCTION || lexdep->isOp(JSOP_CALLEE))) { /* * Mark this formerly-Algol-like function as an escaping @@ -1226,7 +1226,7 @@ Parser::markFunArgs(JSFunctionBox *funbox) */ lexdep->setFunArg(); - JSFunctionBox *afunbox; + FunctionBox *afunbox; if (lexdep->isOp(JSOP_CALLEE)) { /* * A named function expression will not appear to be a @@ -1264,12 +1264,12 @@ Parser::markFunArgs(JSFunctionBox *funbox) } static uint32 -MinBlockId(JSParseNode *fn, uint32 id) +MinBlockId(ParseNode *fn, uint32 id) { if (fn->pn_blockid < id) return false; if (fn->isDefn()) { - for (JSParseNode *pn = fn->dn_uses; pn; pn = pn->pn_link) { + for (ParseNode *pn = fn->dn_uses; pn; pn = pn->pn_link) { if (pn->pn_blockid < id) return false; } @@ -1278,7 +1278,7 @@ MinBlockId(JSParseNode *fn, uint32 id) } static inline bool -CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) +CanFlattenUpvar(Definition *dn, FunctionBox *funbox, uint32 tcflags) { /* * Consider the current function (the lambda, innermost below) using a var @@ -1298,7 +1298,7 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) * flat closure. Uncommenting the early call to g makes this optimization * unsafe (z could name a global setter that calls its argument). */ - JSFunctionBox *afunbox = funbox; + FunctionBox *afunbox = funbox; uintN dnLevel = dn->frameLevel(); JS_ASSERT(dnLevel <= funbox->level); @@ -1367,8 +1367,8 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) if (!dn->isInitialized()) return false; - JSDefinition::Kind dnKind = dn->kind(); - if (dnKind != JSDefinition::CONST) { + Definition::Kind dnKind = dn->kind(); + if (dnKind != Definition::CONST) { if (dn->isAssigned()) return false; @@ -1381,9 +1381,9 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) * definition or expression, afunbox->parent will be null. The body * source might use |arguments| outside of any nested functions it may * contain, so we have to check the tcflags parameter that was passed - * in from Compiler::compileFunctionBody. + * in from BytecodeCompiler::compileFunctionBody. */ - if (dnKind == JSDefinition::ARG && + if (dnKind == Definition::ARG && ((afunbox->parent ? afunbox->parent->tcflags : tcflags) & TCF_FUN_USES_ARGUMENTS)) { return false; } @@ -1394,7 +1394,7 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) * their uses thanks to hoisting. Other binding forms hoist as undefined, * of course, so check forward-reference and blockid relations. */ - if (dnKind != JSDefinition::FUNCTION) { + if (dnKind != Definition::FUNCTION) { /* * Watch out for code such as * @@ -1419,7 +1419,7 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags) } static void -FlagHeavyweights(JSDefinition *dn, JSFunctionBox *funbox, uint32 *tcflags) +FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32 *tcflags) { uintN dnLevel = dn->frameLevel(); @@ -1442,11 +1442,11 @@ FlagHeavyweights(JSDefinition *dn, JSFunctionBox *funbox, uint32 *tcflags) } static bool -DeoptimizeUsesWithin(JSDefinition *dn, const TokenPos &pos) +DeoptimizeUsesWithin(Definition *dn, const TokenPos &pos) { uintN ndeoptimized = 0; - for (JSParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { + for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { JS_ASSERT(pnu->isUsed()); JS_ASSERT(!pnu->isDefn()); if (pnu->pn_pos.begin >= pos.begin && pnu->pn_pos.end <= pos.end) { @@ -1459,7 +1459,7 @@ DeoptimizeUsesWithin(JSDefinition *dn, const TokenPos &pos) } static void -ConsiderUnbranding(JSFunctionBox *funbox) +ConsiderUnbranding(FunctionBox *funbox) { /* * We've already recursively set our kids' kinds, which also classifies @@ -1474,7 +1474,7 @@ ConsiderUnbranding(JSFunctionBox *funbox) bool returnsExpr = !!(funbox->tcflags & TCF_RETURN_EXPR); #if JS_HAS_EXPR_CLOSURES { - JSParseNode *pn2 = funbox->node->pn_body; + ParseNode *pn2 = funbox->node->pn_body; if (pn2->isKind(TOK_UPVARS)) pn2 = pn2->pn_tree; if (pn2->isKind(TOK_ARGSBODY)) @@ -1486,7 +1486,7 @@ ConsiderUnbranding(JSFunctionBox *funbox) if (!returnsExpr) { uintN methodSets = 0, slowMethodSets = 0; - for (JSParseNode *method = funbox->methods; method; method = method->pn_link) { + for (ParseNode *method = funbox->methods; method; method = method->pn_link) { JS_ASSERT(method->isOp(JSOP_LAMBDA) || method->isOp(JSOP_LAMBDA_FC)); ++methodSets; if (!method->pn_funbox->joinable()) @@ -1499,11 +1499,11 @@ ConsiderUnbranding(JSFunctionBox *funbox) } void -Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags) +Parser::setFunctionKinds(FunctionBox *funbox, uint32 *tcflags) { for (; funbox; funbox = funbox->siblings) { - JSParseNode *fn = funbox->node; - JSParseNode *pn = fn->pn_body; + ParseNode *fn = funbox->node; + ParseNode *pn = fn->pn_body; if (funbox->kids) { setFunctionKinds(funbox->kids, tcflags); @@ -1532,8 +1532,8 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags) * value into a flat closure slot when the closure is formed. */ for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - JSDefinition *defn = r.front().value(); - JSDefinition *lexdep = defn->resolve(); + Definition *defn = r.front().value(); + Definition *lexdep = defn->resolve(); if (!lexdep->isFreeVar()) { hasUpvars = true; @@ -1587,8 +1587,8 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags) JS_ASSERT(!upvars->empty()); for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) { - JSDefinition *defn = r.front().value(); - JSDefinition *lexdep = defn->resolve(); + Definition *defn = r.front().value(); + Definition *lexdep = defn->resolve(); if (!lexdep->isFreeVar()) FlagHeavyweights(lexdep, funbox, tcflags); } @@ -1600,7 +1600,7 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags) } /* - * Walk the JSFunctionBox tree looking for functions whose call objects may + * Walk the FunctionBox tree looking for functions whose call objects may * acquire new bindings as they execute: non-strict functions that call eval, * and functions that contain function statements (definitions not appearing * within the top statement list, which don't take effect unless they are @@ -1611,7 +1611,7 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags) * js::Bindings::extensibleParents explain why. */ void -Parser::markExtensibleScopeDescendants(JSFunctionBox *funbox, bool hasExtensibleParent) +Parser::markExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent) { for (; funbox; funbox = funbox->siblings) { /* @@ -1631,17 +1631,17 @@ Parser::markExtensibleScopeDescendants(JSFunctionBox *funbox, bool hasExtensible } } -static JSFunctionBox * -EnterFunction(JSParseNode *fn, JSTreeContext *funtc, JSAtom *funAtom = NULL, +static FunctionBox * +EnterFunction(ParseNode *fn, TreeContext *funtc, JSAtom *funAtom = NULL, FunctionSyntaxKind kind = Expression) { - JSTreeContext *tc = funtc->parent; + TreeContext *tc = funtc->parent; JSFunction *fun = tc->parser->newFunction(tc, funAtom, kind); if (!fun) return NULL; /* Create box for fun->object early to protect against last-ditch GC. */ - JSFunctionBox *funbox = tc->parser->newFunctionBox(fun, fn, tc); + FunctionBox *funbox = tc->parser->newFunctionBox(fun, fn, tc); if (!funbox) return NULL; @@ -1659,13 +1659,13 @@ EnterFunction(JSParseNode *fn, JSTreeContext *funtc, JSAtom *funAtom = NULL, } static bool -LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NULL, +LeaveFunction(ParseNode *fn, TreeContext *funtc, PropertyName *funName = NULL, FunctionSyntaxKind kind = Expression) { - JSTreeContext *tc = funtc->parent; + TreeContext *tc = funtc->parent; tc->blockidGen = funtc->blockidGen; - JSFunctionBox *funbox = fn->pn_funbox; + FunctionBox *funbox = fn->pn_funbox; funbox->tcflags |= funtc->flags & (TCF_FUN_FLAGS | TCF_COMPILE_N_GO | TCF_RETURN_EXPR); fn->pn_dflags |= PND_INITIALIZED; @@ -1684,7 +1684,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL for (AtomDefnRange r = funtc->lexdeps->all(); !r.empty(); r.popFront()) { JSAtom *atom = r.front().key(); - JSDefinition *dn = r.front().value(); + Definition *dn = r.front().value(); JS_ASSERT(dn->isPlaceholder()); if (atom == funName && kind == Expression) { @@ -1710,7 +1710,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL * backward-reference case; this is the hard forward-reference * case where we pay a higher price. */ - for (JSParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { + for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) { if (pnu->isAssigned() && pnu->pn_blockid >= funtc->bodyid) { funbox->tcflags |= TCF_FUN_SETS_OUTER_NAME; break; @@ -1718,7 +1718,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL } } - JSDefinition *outer_dn = tc->decls.lookupFirst(atom); + Definition *outer_dn = tc->decls.lookupFirst(atom); /* * Make sure to deoptimize lexical dependencies that are polluted @@ -1776,8 +1776,8 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL * case), and nowhere else, currently. */ if (dn != outer_dn) { - JSParseNode **pnup = &dn->dn_uses; - JSParseNode *pnu; + ParseNode **pnup = &dn->dn_uses; + ParseNode *pnu; while ((pnu = *pnup) != NULL) { pnu->pn_lexdef = outer_dn; @@ -1788,7 +1788,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL * Make dn be a use that redirects to outer_dn, because we * can't replace dn with outer_dn in all the pn_namesets in * the AST where it may be. Instead we make it forward to - * outer_dn. See JSDefinition::resolve. + * outer_dn. See Definition::resolve. */ *pnup = outer_dn->dn_uses; outer_dn->dn_uses = dn; @@ -1803,7 +1803,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL } if (funtc->lexdeps->count() - foundCallee != 0) { - JSParseNode *body = fn->pn_body; + ParseNode *body = fn->pn_body; fn->pn_body = NameSetNode::create(tc); if (!fn->pn_body) @@ -1832,10 +1832,10 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL */ if (funtc->inStrictMode() && funbox->object->getFunctionPrivate()->nargs > 0) { AtomDeclsIter iter(&funtc->decls); - JSDefinition *dn; + Definition *dn; while ((dn = iter()) != NULL) { - if (dn->kind() == JSDefinition::ARG && dn->isAssigned()) { + if (dn->kind() == Definition::ARG && dn->isAssigned()) { funbox->tcflags |= TCF_FUN_MUTATES_PARAMETER; break; } @@ -1848,7 +1848,7 @@ LeaveFunction(JSParseNode *fn, JSTreeContext *funtc, PropertyName *funName = NUL } static bool -DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, PropertyName *name); +DefineGlobal(ParseNode *pn, CodeGenerator *cg, PropertyName *name); /* * FIXME? this Parser method was factored from Parser::functionDef with minimal @@ -1857,7 +1857,7 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, PropertyName *name); * parameters. */ bool -Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNode **listp) +Parser::functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **listp) { if (tokenStream.getToken() != TOK_LP) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_PAREN_BEFORE_FORMAL); @@ -1868,7 +1868,7 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo #if JS_HAS_DESTRUCTURING JSAtom *duplicatedArg = NULL; bool destructuringArg = false; - JSParseNode *list = NULL; + ParseNode *list = NULL; #endif do { @@ -1892,7 +1892,7 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo data.pn = NULL; data.op = JSOP_DEFVAR; data.binder = BindDestructuringArg; - JSParseNode *lhs = destructuringExpr(&data, tt); + ParseNode *lhs = destructuringExpr(&data, tt); if (!lhs) return false; @@ -1909,7 +1909,7 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo * anonymous positional parameter into the destructuring * left-hand-side expression and accumulate it in list. */ - JSParseNode *rhs = NameNode::create(context->runtime->atomState.emptyAtom, &funtc); + ParseNode *rhs = NameNode::create(context->runtime->atomState.emptyAtom, &funtc); if (!rhs) return false; rhs->setKind(TOK_NAME); @@ -1917,8 +1917,8 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo rhs->pn_cookie.set(funtc.staticLevel, slot); rhs->pn_dflags |= PND_BOUND; - JSParseNode *item = - JSParseNode::newBinaryOrAppend(TOK_ASSIGN, JSOP_NOP, lhs, rhs, &funtc); + ParseNode *item = + ParseNode::newBinaryOrAppend(TOK_ASSIGN, JSOP_NOP, lhs, rhs, &funtc); if (!item) return false; if (!list) { @@ -1978,7 +1978,7 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo #if JS_HAS_DESTRUCTURING report_dup_and_destructuring: - JSDefinition *dn = funtc.decls.lookupFirst(duplicatedArg); + Definition *dn = funtc.decls.lookupFirst(duplicatedArg); reportErrorNumber(dn, JSREPORT_ERROR, JSMSG_DESTRUCT_DUP_ARG); return false; #endif @@ -1994,14 +1994,14 @@ Parser::functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNo return true; } -JSParseNode * +ParseNode * Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind kind) { JS_ASSERT_IF(kind == Statement, funName); /* Make a TOK_FUNCTION node. */ tokenStream.mungeCurrentToken(TOK_FUNCTION, JSOP_NOP); - JSParseNode *pn = FunctionNode::create(tc); + ParseNode *pn = FunctionNode::create(tc); if (!pn) return NULL; pn->pn_body = NULL; @@ -2024,28 +2024,28 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind * avoid optimizing variable references that might name a function. */ if (kind == Statement) { - if (JSDefinition *dn = tc->decls.lookupFirst(funName)) { - JSDefinition::Kind dn_kind = dn->kind(); + if (Definition *dn = tc->decls.lookupFirst(funName)) { + Definition::Kind dn_kind = dn->kind(); JS_ASSERT(!dn->isUsed()); JS_ASSERT(dn->isDefn()); - if (context->hasStrictOption() || dn_kind == JSDefinition::CONST) { + if (context->hasStrictOption() || dn_kind == Definition::CONST) { JSAutoByteString name; if (!js_AtomToPrintableString(context, funName, &name) || !reportErrorNumber(NULL, - (dn_kind != JSDefinition::CONST) + (dn_kind != Definition::CONST) ? JSREPORT_WARNING | JSREPORT_STRICT : JSREPORT_ERROR, JSMSG_REDECLARED_VAR, - JSDefinition::kindString(dn_kind), + Definition::kindString(dn_kind), name.ptr())) { return NULL; } } if (bodyLevel) { - tc->decls.updateFirst(funName, (JSDefinition *) pn); + tc->decls.updateFirst(funName, (Definition *) pn); pn->setDefn(true); pn->dn_uses = dn; /* dn->dn_uses is now pn_link */ @@ -2059,7 +2059,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind * put in tc->lexdeps on first forward reference, and recycle pn. */ - if (JSDefinition *fn = tc->lexdeps.lookupDefn(funName)) { + if (Definition *fn = tc->lexdeps.lookupDefn(funName)) { JS_ASSERT(fn->isDefn()); fn->setKind(TOK_FUNCTION); fn->setArity(PN_FUNC); @@ -2075,7 +2075,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind fn->pn_cookie.makeFree(); tc->lexdeps->remove(funName); - RecycleTree(pn, tc); + freeTree(pn); pn = fn; } @@ -2088,8 +2088,8 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind * variable to bind its name to its value, and not an activation object * property (it might also need the activation property, if the outer * function contains with statements, e.g., but the stack slot wins - * when jsemit.cpp's BindNameToSlot can optimize a JSOP_NAME into a - * JSOP_GETLOCAL bytecode). + * when BytecodeGenerator.cpp's BindNameToSlot can optimize a JSOP_NAME + * into a JSOP_GETLOCAL bytecode). */ if (bodyLevel && tc->inFunction()) { /* @@ -2118,21 +2118,21 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind } } - JSTreeContext *outertc = tc; + TreeContext *outertc = tc; /* Initialize early for possible flags mutation via destructuringExpr. */ - JSTreeContext funtc(tc->parser); + TreeContext funtc(tc->parser); if (!funtc.init(context)) return NULL; - JSFunctionBox *funbox = EnterFunction(pn, &funtc, funName, kind); + FunctionBox *funbox = EnterFunction(pn, &funtc, funName, kind); if (!funbox) return NULL; JSFunction *fun = funbox->function(); /* Now parse formal argument list and compute fun->nargs. */ - JSParseNode *prelude = NULL; + ParseNode *prelude = NULL; if (!functionArguments(funtc, funbox, &prelude)) return NULL; @@ -2150,7 +2150,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind if (prelude) { AtomDeclsIter iter(&funtc.decls); - while (JSDefinition *apn = iter()) { + while (Definition *apn = iter()) { /* Filter based on pn_op -- see BindDestructuringArg, above. */ if (!apn->isOp(JSOP_SETLOCAL)) continue; @@ -2182,7 +2182,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY); #endif - JSParseNode *body = functionBody(); + ParseNode *body = functionBody(); if (!body) return NULL; @@ -2227,7 +2227,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind */ if (prelude) { if (!body->isArity(PN_LIST)) { - JSParseNode *block; + ParseNode *block; block = ListNode::create(outertc); if (!block) @@ -2239,7 +2239,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind body = block; } - JSParseNode *item = UnaryNode::create(outertc); + ParseNode *item = UnaryNode::create(outertc); if (!item) return NULL; @@ -2321,7 +2321,7 @@ Parser::functionDef(PropertyName *funName, FunctionType type, FunctionSyntaxKind return pn; } -JSParseNode * +ParseNode * Parser::functionStmt() { PropertyName *name = NULL; @@ -2342,7 +2342,7 @@ Parser::functionStmt() return functionDef(name, Normal, Statement); } -JSParseNode * +ParseNode * Parser::functionExpr() { PropertyName *name = NULL; @@ -2373,13 +2373,13 @@ Parser::functionExpr() * to the "use strict" statement, which is indeed a directive. */ bool -Parser::recognizeDirectivePrologue(JSParseNode *pn, bool *isDirectivePrologueMember) +Parser::recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember) { *isDirectivePrologueMember = pn->isStringExprStatement(); if (!*isDirectivePrologueMember) return true; - JSParseNode *kid = pn->pn_kid; + ParseNode *kid = pn->pn_kid; if (kid->isEscapeFreeStringLiteral()) { /* * Mark this statement as being a possibly legitimate part of a @@ -2428,10 +2428,10 @@ Parser::recognizeDirectivePrologue(JSParseNode *pn, bool *isDirectivePrologueMem * statements' trees. If called from block-parsing code, the caller must * match { before and } after. */ -JSParseNode * +ParseNode * Parser::statements() { - JSParseNode *pn, *pn2, *saveBlock; + ParseNode *pn, *pn2, *saveBlock; TokenKind tt; JS_CHECK_RECURSION(context, return NULL); @@ -2501,10 +2501,10 @@ Parser::statements() return pn; } -JSParseNode * +ParseNode * Parser::condition() { - JSParseNode *pn; + ParseNode *pn; MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND); pn = parenExpr(); @@ -2523,7 +2523,7 @@ Parser::condition() } static bool -MatchLabel(JSContext *cx, TokenStream *ts, JSParseNode *pn) +MatchLabel(JSContext *cx, TokenStream *ts, ParseNode *pn) { TokenKind tt = ts->peekTokenSameLine(TSF_OPERAND); if (tt == TOK_ERROR) @@ -2549,9 +2549,9 @@ MatchLabel(JSContext *cx, TokenStream *ts, JSParseNode *pn) * data->pn in a slot of the block object. */ static JSBool -BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) +BindLet(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc) { - JSParseNode *pn; + ParseNode *pn; JSObject *blockObj; jsint n; @@ -2566,7 +2566,7 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) return false; blockObj = tc->blockChain(); - JSDefinition *dn = tc->decls.lookupFirst(atom); + Definition *dn = tc->decls.lookupFirst(atom); if (dn && dn->pn_blockid == tc->blockid()) { JSAutoByteString name; if (js_AtomToPrintableString(cx, atom, &name)) { @@ -2596,8 +2596,8 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) * Assign block-local index to pn->pn_cookie right away, encoding it as an * upvar cookie whose skip tells the current static level. The emitter will * adjust the node's slot based on its stack depth model -- and, for global - * and eval code, Compiler::compileScript will adjust the slot again to - * include script->nfixed. + * and eval code, BytecodeCompiler::compileScript will adjust the slot + * again to include script->nfixed. */ pn->setOp(JSOP_GETLOCAL); pn->pn_cookie.set(tc->staticLevel, uint16(n)); @@ -2615,17 +2615,17 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) * Store pn temporarily in what would be shape-mapped slots in a cloned * block object (once the prototype's final population is known, after all * 'let' bindings for this block have been parsed). We free these slots in - * jsemit.cpp:EmitEnterBlock so they don't tie up unused space in the so- - * called "static" prototype Block. + * BytecodeGenerator.cpp:EmitEnterBlock so they don't tie up unused space + * in the so-called "static" prototype Block. */ blockObj->setSlot(shape->slot, PrivateValue(pn)); return true; } static void -PopStatement(JSTreeContext *tc) +PopStatement(TreeContext *tc) { - JSStmtInfo *stmt = tc->topStmt; + StmtInfo *stmt = tc->topStmt; if (stmt->flags & SIF_SCOPE) { JSObject *obj = stmt->blockBox->object; @@ -2640,14 +2640,14 @@ PopStatement(JSTreeContext *tc) tc->decls.remove(atom); } } - js_PopStatement(tc); + PopStatementTC(tc); } static inline bool -OuterLet(JSTreeContext *tc, JSStmtInfo *stmt, JSAtom *atom) +OuterLet(TreeContext *tc, StmtInfo *stmt, JSAtom *atom) { while (stmt->downScope) { - stmt = js_LexicalLookup(tc, atom, NULL, stmt->downScope); + stmt = LexicalLookup(tc, atom, NULL, stmt->downScope); if (!stmt) return false; if (stmt->type == STMT_BLOCK) @@ -2672,7 +2672,7 @@ OuterLet(JSTreeContext *tc, JSStmtInfo *stmt, JSAtom *atom) * stack frame slots. */ static bool -DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, PropertyName *name) +DefineGlobal(ParseNode *pn, CodeGenerator *cg, PropertyName *name) { GlobalScope *globalScope = cg->compiler()->globalScope; JSObject *globalObj = globalScope->globalObj; @@ -2689,7 +2689,7 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, PropertyName *name) if (!globalObj->lookupProperty(cx, name, &holder, &prop)) return false; - JSFunctionBox *funbox = pn->isKind(TOK_FUNCTION) ? pn->pn_funbox : NULL; + FunctionBox *funbox = pn->isKind(TOK_FUNCTION) ? pn->pn_funbox : NULL; GlobalScope::GlobalDef def; if (prop) { @@ -2749,7 +2749,7 @@ DefineGlobal(JSParseNode *pn, JSCodeGenerator *cg, PropertyName *name) } static bool -BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSTreeContext *tc) +BindTopLevelVar(JSContext *cx, BindData *data, ParseNode *pn, TreeContext *tc) { JS_ASSERT(pn->isOp(JSOP_NAME)); JS_ASSERT(!tc->inFunction()); @@ -2802,11 +2802,11 @@ BindTopLevelVar(JSContext *cx, BindData *data, JSParseNode *pn, JSTreeContext *t } static bool -BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSTreeContext *tc) +BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, TreeContext *tc) { JS_ASSERT(tc->inFunction()); - JSParseNode *pn = data->pn; + ParseNode *pn = data->pn; JSAtom *name = pn->pn_atom; /* @@ -2840,7 +2840,7 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSTreeCont if (kind == ARGUMENT) { JS_ASSERT(tc->inFunction()); - JS_ASSERT(!mdl.empty() && mdl.front()->kind() == JSDefinition::ARG); + JS_ASSERT(!mdl.empty() && mdl.front()->kind() == Definition::ARG); } else { JS_ASSERT(kind == VARIABLE || kind == CONSTANT); } @@ -2849,9 +2849,9 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, JSTreeCont } static JSBool -BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) +BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, TreeContext *tc) { - JSParseNode *pn = data->pn; + ParseNode *pn = data->pn; /* Default best op for pn is JSOP_NAME; we'll try to improve below. */ pn->setOp(JSOP_NAME); @@ -2859,7 +2859,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) if (!CheckStrictBinding(cx, tc, atom->asPropertyName(), pn)) return false; - JSStmtInfo *stmt = js_LexicalLookup(tc, atom, NULL); + StmtInfo *stmt = LexicalLookup(tc, atom, NULL); if (stmt && stmt->type == STMT_WITH) { data->fresh = false; @@ -2872,10 +2872,10 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) JSOp op = data->op; if (stmt || !mdl.empty()) { - JSDefinition *dn = mdl.empty() ? NULL : mdl.front(); - JSDefinition::Kind dn_kind = dn ? dn->kind() : JSDefinition::VAR; + Definition *dn = mdl.empty() ? NULL : mdl.front(); + Definition::Kind dn_kind = dn ? dn->kind() : Definition::VAR; - if (dn_kind == JSDefinition::ARG) { + if (dn_kind == Definition::ARG) { JSAutoByteString name; if (!js_AtomToPrintableString(cx, atom, &name)) return JS_FALSE; @@ -2893,12 +2893,12 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) } } else { bool error = (op == JSOP_DEFCONST || - dn_kind == JSDefinition::CONST || - (dn_kind == JSDefinition::LET && + dn_kind == Definition::CONST || + (dn_kind == Definition::LET && (stmt->type != STMT_CATCH || OuterLet(tc, stmt, atom)))); if (cx->hasStrictOption() - ? op != JSOP_DEFVAR || dn_kind != JSDefinition::VAR + ? op != JSOP_DEFVAR || dn_kind != Definition::VAR : error) { JSAutoByteString name; if (!js_AtomToPrintableString(cx, atom, &name) || @@ -2907,7 +2907,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) ? JSREPORT_WARNING | JSREPORT_STRICT : JSREPORT_ERROR, JSMSG_REDECLARED_VAR, - JSDefinition::kindString(dn_kind), + Definition::kindString(dn_kind), name.ptr())) { return JS_FALSE; } @@ -2930,13 +2930,13 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) * There the x definition is hoisted but the x = 2 assignment mutates * the block-local binding of x. */ - JSDefinition *dn = mdl.front(); + Definition *dn = mdl.front(); data->fresh = false; if (!pn->isUsed()) { /* Make pnu be a fresh name node that uses dn. */ - JSParseNode *pnu = pn; + ParseNode *pnu = pn; if (pn->isDefn()) { pnu = NameNode::create(atom, tc); @@ -2949,7 +2949,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) } /* Find the first non-let binding of this atom. */ - while (dn->kind() == JSDefinition::LET) { + while (dn->kind() == Definition::LET) { mdl.popFront(); if (mdl.empty()) break; @@ -2958,7 +2958,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) if (dn) { JS_ASSERT_IF(data->op == JSOP_DEFCONST, - dn->kind() == JSDefinition::CONST); + dn->kind() == Definition::CONST); return JS_TRUE; } @@ -2971,7 +2971,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) if (tc->lexdeps->lookup(atom)) { tc->lexdeps->remove(atom); } else { - JSParseNode *pn2 = NameNode::create(atom, tc); + ParseNode *pn2 = NameNode::create(atom, tc); if (!pn2) return JS_FALSE; @@ -2983,7 +2983,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) pn->setOp(JSOP_NAME); } - if (!tc->decls.addHoist(atom, (JSDefinition *) pn)) + if (!tc->decls.addHoist(atom, (Definition *) pn)) return JS_FALSE; pn->setDefn(true); pn->pn_dflags &= ~PND_PLACEHOLDER; @@ -2999,7 +2999,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc) } static bool -MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg) +MakeSetCall(JSContext *cx, ParseNode *pn, TreeContext *tc, uintN msg) { JS_ASSERT(pn->isArity(PN_LIST)); JS_ASSERT(pn->isOp(JSOP_CALL) || pn->isOp(JSOP_EVAL) || @@ -3007,7 +3007,7 @@ MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg) if (!ReportStrictModeError(cx, TS(tc->parser), tc, pn, msg)) return false; - JSParseNode *pn2 = pn->pn_head; + ParseNode *pn2 = pn->pn_head; if (pn2->isKind(TOK_FUNCTION) && (pn2->pn_funbox->tcflags & TCF_GENEXP_LAMBDA)) { ReportCompileErrorNumber(cx, TS(tc->parser), pn, JSREPORT_ERROR, msg); return false; @@ -3017,10 +3017,10 @@ MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg) } static void -NoteLValue(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN dflag = PND_ASSIGNED) +NoteLValue(JSContext *cx, ParseNode *pn, TreeContext *tc, uintN dflag = PND_ASSIGNED) { if (pn->isUsed()) { - JSDefinition *dn = pn->pn_lexdef; + Definition *dn = pn->pn_lexdef; /* * Save the win of PND_INITIALIZED if we can prove 'var x;' and 'x = y' @@ -3064,8 +3064,7 @@ NoteLValue(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN dflag = PND_ #if JS_HAS_DESTRUCTURING static JSBool -BindDestructuringVar(JSContext *cx, BindData *data, JSParseNode *pn, - JSTreeContext *tc) +BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, TreeContext *tc) { JSAtom *atom; @@ -3120,7 +3119,7 @@ BindDestructuringVar(JSContext *cx, BindData *data, JSParseNode *pn, * which can be optimized further. So we select JSOP_SETNAME. */ static JSBool -BindDestructuringLHS(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) +BindDestructuringLHS(JSContext *cx, ParseNode *pn, TreeContext *tc) { switch (pn->getKind()) { case TOK_NAME: @@ -3202,7 +3201,7 @@ BindDestructuringLHS(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) * match. */ static bool -CheckDestructuring(JSContext *cx, BindData *data, JSParseNode *left, JSTreeContext *tc) +CheckDestructuring(JSContext *cx, BindData *data, ParseNode *left, TreeContext *tc) { bool ok; @@ -3213,7 +3212,7 @@ CheckDestructuring(JSContext *cx, BindData *data, JSParseNode *left, JSTreeConte } if (left->isKind(TOK_RB)) { - for (JSParseNode *pn = left->pn_head; pn; pn = pn->pn_next) { + for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) { /* Nullary comma is an elision; binary comma is an expression.*/ if (!pn->isKind(TOK_COMMA) || !pn->isArity(PN_NULLARY)) { if (pn->isKind(TOK_RB) || pn->isKind(TOK_RC)) { @@ -3236,9 +3235,9 @@ CheckDestructuring(JSContext *cx, BindData *data, JSParseNode *left, JSTreeConte } } else { JS_ASSERT(left->isKind(TOK_RC)); - for (JSParseNode *pair = left->pn_head; pair; pair = pair->pn_next) { + for (ParseNode *pair = left->pn_head; pair; pair = pair->pn_next) { JS_ASSERT(pair->isKind(TOK_COLON)); - JSParseNode *pn = pair->pn_right; + ParseNode *pn = pair->pn_right; if (pn->isKind(TOK_RB) || pn->isKind(TOK_RC)) { ok = CheckDestructuring(cx, data, pn, tc); @@ -3307,10 +3306,10 @@ CheckDestructuring(JSContext *cx, BindData *data, JSParseNode *left, JSTreeConte * functions, you might have to change the other to match. */ static void -UndominateInitializers(JSParseNode *left, const TokenPtr &end, JSTreeContext *tc) +UndominateInitializers(ParseNode *left, const TokenPtr &end, TreeContext *tc) { if (left->isKind(TOK_RB)) { - for (JSParseNode *pn = left->pn_head; pn; pn = pn->pn_next) { + for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) { /* Nullary comma is an elision; binary comma is an expression.*/ if (!pn->isKind(TOK_COMMA) || !pn->isArity(PN_NULLARY)) { if (pn->isKind(TOK_RB) || pn->isKind(TOK_RC)) @@ -3322,9 +3321,9 @@ UndominateInitializers(JSParseNode *left, const TokenPtr &end, JSTreeContext *tc } else { JS_ASSERT(left->isKind(TOK_RC)); - for (JSParseNode *pair = left->pn_head; pair; pair = pair->pn_next) { + for (ParseNode *pair = left->pn_head; pair; pair = pair->pn_next) { JS_ASSERT(pair->isKind(TOK_COLON)); - JSParseNode *pn = pair->pn_right; + ParseNode *pn = pair->pn_right; if (pn->isKind(TOK_RB) || pn->isKind(TOK_RC)) UndominateInitializers(pn, end, tc); else @@ -3333,13 +3332,11 @@ UndominateInitializers(JSParseNode *left, const TokenPtr &end, JSTreeContext *tc } } -JSParseNode * +ParseNode * Parser::destructuringExpr(BindData *data, TokenKind tt) { - JSParseNode *pn; - tc->flags |= TCF_DECL_DESTRUCTURING; - pn = primaryExpr(tt, JS_FALSE); + ParseNode *pn = primaryExpr(tt, JS_FALSE); tc->flags &= ~TCF_DECL_DESTRUCTURING; if (!pn) return NULL; @@ -3350,11 +3347,11 @@ Parser::destructuringExpr(BindData *data, TokenKind tt) #endif /* JS_HAS_DESTRUCTURING */ -JSParseNode * +ParseNode * Parser::returnOrYield(bool useAssignExpr) { TokenKind tt, tt2; - JSParseNode *pn, *pn2; + ParseNode *pn, *pn2; tt = tokenStream.currentToken().type; if (!tc->inFunction()) { @@ -3429,27 +3426,22 @@ Parser::returnOrYield(bool useAssignExpr) return pn; } -static JSParseNode * -PushLexicalScope(JSContext *cx, TokenStream *ts, JSTreeContext *tc, - JSStmtInfo *stmt) +static ParseNode * +PushLexicalScope(JSContext *cx, TokenStream *ts, TreeContext *tc, StmtInfo *stmt) { - JSParseNode *pn; - JSObject *obj; - JSObjectBox *blockbox; - - pn = LexicalScopeNode::create(tc); + ParseNode *pn = LexicalScopeNode::create(tc); if (!pn) return NULL; - obj = js_NewBlockObject(cx); + JSObject *obj = js_NewBlockObject(cx); if (!obj) return NULL; - blockbox = tc->parser->newObjectBox(obj); + ObjectBox *blockbox = tc->parser->newObjectBox(obj); if (!blockbox) return NULL; - js_PushBlockScope(tc, stmt, blockbox, -1); + PushBlockScope(tc, stmt, blockbox, -1); pn->setKind(TOK_LEXICALSCOPE); pn->setOp(JSOP_LEAVEBLOCK); pn->pn_objbox = blockbox; @@ -3463,11 +3455,11 @@ PushLexicalScope(JSContext *cx, TokenStream *ts, JSTreeContext *tc, #if JS_HAS_BLOCK_SCOPE -JSParseNode * +ParseNode * Parser::letBlock(JSBool statement) { - JSParseNode *pn, *pnblock, *pnlet; - JSStmtInfo stmtInfo; + ParseNode *pn, *pnblock, *pnlet; + StmtInfo stmtInfo; JS_ASSERT(tokenStream.currentToken().type == TOK_LET); @@ -3544,16 +3536,16 @@ Parser::letBlock(JSBool statement) #endif /* JS_HAS_BLOCK_SCOPE */ static bool -PushBlocklikeStatement(JSStmtInfo *stmt, JSStmtType type, JSTreeContext *tc) +PushBlocklikeStatement(StmtInfo *stmt, StmtType type, TreeContext *tc) { - js_PushStatement(tc, stmt, type, -1); + PushStatement(tc, stmt, type, -1); return GenerateBlockId(tc, stmt->blockid); } -static JSParseNode * -NewBindingNode(JSAtom *atom, JSTreeContext *tc, bool let = false) +static ParseNode * +NewBindingNode(JSAtom *atom, TreeContext *tc, bool let = false) { - JSParseNode *pn; + ParseNode *pn; AtomDefnPtr removal; if ((pn = tc->decls.lookupFirst(atom))) { @@ -3596,19 +3588,19 @@ NewBindingNode(JSAtom *atom, JSTreeContext *tc, bool let = false) return pn; } -JSParseNode * +ParseNode * Parser::switchStatement() { - JSParseNode *pn5, *saveBlock; + ParseNode *pn5, *saveBlock; JSBool seenDefault = JS_FALSE; - JSParseNode *pn = BinaryNode::create(tc); + ParseNode *pn = BinaryNode::create(tc); if (!pn) return NULL; MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH); /* pn1 points to the switch's discriminant. */ - JSParseNode *pn1 = parenExpr(); + ParseNode *pn1 = parenExpr(); if (!pn1) return NULL; @@ -3619,11 +3611,11 @@ Parser::switchStatement() * NB: we must push stmtInfo before calling GenerateBlockIdForStmtNode * because that function states tc->topStmt->blockid. */ - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_SWITCH, -1); /* pn2 is a list of case nodes. The default case has pn_left == NULL */ - JSParseNode *pn2 = ListNode::create(tc); + ParseNode *pn2 = ListNode::create(tc); if (!pn2) return NULL; pn2->makeEmpty(); @@ -3634,7 +3626,7 @@ Parser::switchStatement() TokenKind tt; while ((tt = tokenStream.getToken()) != TOK_RC) { - JSParseNode *pn3; + ParseNode *pn3; switch (tt) { case TOK_DEFAULT: if (seenDefault) { @@ -3671,7 +3663,7 @@ Parser::switchStatement() } MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE); - JSParseNode *pn4 = ListNode::create(tc); + ParseNode *pn4 = ListNode::create(tc); if (!pn4) return NULL; pn4->setKind(TOK_LC); @@ -3711,21 +3703,21 @@ Parser::switchStatement() return pn; } -JSParseNode * +ParseNode * Parser::forStatement() { - JSParseNode *pnseq = NULL; + ParseNode *pnseq = NULL; #if JS_HAS_BLOCK_SCOPE - JSParseNode *pnlet = NULL; - JSStmtInfo blockInfo; + ParseNode *pnlet = NULL; + StmtInfo blockInfo; #endif /* A FOR node is binary, left is loop control and right is the body. */ - JSParseNode *pn = BinaryNode::create(tc); + ParseNode *pn = BinaryNode::create(tc); if (!pn) return NULL; - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1); pn->setOp(JSOP_ITER); pn->pn_iflags = 0; @@ -3743,7 +3735,7 @@ Parser::forStatement() bool let = false; #endif - JSParseNode *pn1; + ParseNode *pn1; if (tt == TOK_SEMI) { if (pn->pn_iflags & JSITER_FOREACH) { reportErrorNumber(pn, JSREPORT_ERROR, JSMSG_BAD_FOR_EACH_LOOP); @@ -3797,10 +3789,10 @@ Parser::forStatement() * We can be sure that it's a for/in loop if there's still an 'in' * keyword here, even if JavaScript recognizes 'in' as an operator, * as we've excluded 'in' from being parsed in RelExpr by setting - * the TCF_IN_FOR_INIT flag in our JSTreeContext. + * the TCF_IN_FOR_INIT flag in our TreeContext. */ - JSParseNode *pn2, *pn3; - JSParseNode *pn4 = TernaryNode::create(tc); + ParseNode *pn2, *pn3; + ParseNode *pn4 = TernaryNode::create(tc); if (!pn4) return NULL; if (pn1 && tokenStream.matchToken(TOK_IN)) { @@ -3961,7 +3953,7 @@ Parser::forStatement() * 'for (let x in y)' loop. */ #if JS_HAS_BLOCK_SCOPE - JSStmtInfo *save = tc->topStmt; + StmtInfo *save = tc->topStmt; if (let) tc->topStmt = save->down; #endif @@ -4038,10 +4030,10 @@ Parser::forStatement() return pn; } -JSParseNode * +ParseNode * Parser::tryStatement() { - JSParseNode *catchList, *lastCatch; + ParseNode *catchList, *lastCatch; /* * try nodes are ternary. @@ -4060,13 +4052,13 @@ Parser::tryStatement() * * finally nodes are TOK_LC statement lists. */ - JSParseNode *pn = TernaryNode::create(tc); + ParseNode *pn = TernaryNode::create(tc); if (!pn) return NULL; pn->setOp(JSOP_NOP); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY); - JSStmtInfo stmtInfo; + StmtInfo stmtInfo; if (!PushBlocklikeStatement(&stmtInfo, STMT_TRY, tc)) return NULL; pn->pn_kid1 = statements(); @@ -4086,7 +4078,7 @@ Parser::tryStatement() lastCatch = NULL; do { - JSParseNode *pnblock; + ParseNode *pnblock; BindData data; /* Check for another catch after unconditional catch. */ @@ -4111,7 +4103,7 @@ Parser::tryStatement() * where lhs is a name or a destructuring left-hand side. * (the latter is legal only #ifdef JS_HAS_CATCH_GUARD) */ - JSParseNode *pn2 = TernaryNode::create(tc); + ParseNode *pn2 = TernaryNode::create(tc); if (!pn2) return NULL; pnblock->pn_expr = pn2; @@ -4128,7 +4120,7 @@ Parser::tryStatement() data.let.overflow = JSMSG_TOO_MANY_CATCH_VARS; tt = tokenStream.getToken(); - JSParseNode *pn3; + ParseNode *pn3; switch (tt) { #if JS_HAS_DESTRUCTURING case TOK_LB: @@ -4204,7 +4196,7 @@ Parser::tryStatement() return pn; } -JSParseNode * +ParseNode * Parser::withStatement() { /* @@ -4220,21 +4212,21 @@ Parser::withStatement() return NULL; } - JSParseNode *pn = BinaryNode::create(tc); + ParseNode *pn = BinaryNode::create(tc); if (!pn) return NULL; MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH); - JSParseNode *pn2 = parenExpr(); + ParseNode *pn2 = parenExpr(); if (!pn2) return NULL; MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH); pn->pn_left = pn2; - JSParseNode *oldWith = tc->innermostWith; + ParseNode *oldWith = tc->innermostWith; tc->innermostWith = pn; - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_WITH, -1); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_WITH, -1); pn2 = statement(); if (!pn2) return NULL; @@ -4250,8 +4242,8 @@ Parser::withStatement() * to safely optimize binding globals (see bug 561923). */ for (AtomDefnRange r = tc->lexdeps->all(); !r.empty(); r.popFront()) { - JSDefinition *defn = r.front().value(); - JSDefinition *lexdep = defn->resolve(); + Definition *defn = r.front().value(); + Definition *lexdep = defn->resolve(); DeoptimizeUsesWithin(lexdep, pn->pn_pos); } @@ -4259,12 +4251,10 @@ Parser::withStatement() } #if JS_HAS_BLOCK_SCOPE -JSParseNode * +ParseNode * Parser::letStatement() { - JSObjectBox *blockbox; - - JSParseNode *pn; + ParseNode *pn; do { /* Check for a let statement or let expression. */ if (tokenStream.peekToken() == TOK_LP) { @@ -4278,17 +4268,17 @@ Parser::letStatement() } /* - * This is a let declaration. We must be directly under a block per - * the proposed ES4 specs, but not an implicit block created due to + * This is a let declaration. We must be directly under a block per the + * proposed ES4 specs, but not an implicit block created due to * 'for (let ...)'. If we pass this error test, make the enclosing - * JSStmtInfo be our scope. Further let declarations in this block - * will find this scope statement and use the same block object. + * StmtInfo be our scope. Further let declarations in this block will + * find this scope statement and use the same block object. * * If we are the first let declaration in this block (i.e., when the - * enclosing maybe-scope JSStmtInfo isn't yet a scope statement) then + * enclosing maybe-scope StmtInfo isn't yet a scope statement) then * we also need to set tc->blockNode to be our TOK_LEXICALSCOPE. */ - JSStmtInfo *stmt = tc->topStmt; + StmtInfo *stmt = tc->topStmt; if (stmt && (!STMT_MAYBE_SCOPE(stmt) || (stmt->flags & SIF_FOR_BLOCK))) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_LET_DECL_NOT_IN_BLOCK); @@ -4330,7 +4320,7 @@ Parser::letStatement() if (!obj) return NULL; - blockbox = tc->parser->newObjectBox(obj); + ObjectBox *blockbox = tc->parser->newObjectBox(obj); if (!blockbox) return NULL; @@ -4350,12 +4340,12 @@ Parser::letStatement() stmt->blockBox = blockbox; #ifdef DEBUG - JSParseNode *tmp = tc->blockNode; + ParseNode *tmp = tc->blockNode; JS_ASSERT(!tmp || !tmp->isKind(TOK_LEXICALSCOPE)); #endif /* Create a new lexical scope node for these statements. */ - JSParseNode *pn1 = LexicalScopeNode::create(tc); + ParseNode *pn1 = LexicalScopeNode::create(tc); if (!pn1) return NULL; @@ -4379,11 +4369,11 @@ Parser::letStatement() } #endif -JSParseNode * +ParseNode * Parser::expressionStatement() { tokenStream.ungetToken(); - JSParseNode *pn2 = expr(); + ParseNode *pn2 = expr(); if (!pn2) return NULL; @@ -4393,7 +4383,7 @@ Parser::expressionStatement() return NULL; } JSAtom *label = pn2->pn_atom; - for (JSStmtInfo *stmt = tc->topStmt; stmt; stmt = stmt->down) { + for (StmtInfo *stmt = tc->topStmt; stmt; stmt = stmt->down) { if (stmt->type == STMT_LABEL && stmt->label == label) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_DUPLICATE_LABEL); return NULL; @@ -4404,10 +4394,10 @@ Parser::expressionStatement() (void) tokenStream.getToken(); /* Push a label struct and parse the statement. */ - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_LABEL, -1); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_LABEL, -1); stmtInfo.label = label; - JSParseNode *pn = statement(); + ParseNode *pn = statement(); if (!pn) return NULL; @@ -4426,7 +4416,7 @@ Parser::expressionStatement() return pn2; } - JSParseNode *pn = UnaryNode::create(tc); + ParseNode *pn = UnaryNode::create(tc); if (!pn) return NULL; pn->setKind(TOK_SEMI); @@ -4468,10 +4458,10 @@ Parser::expressionStatement() return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL; } -JSParseNode * +ParseNode * Parser::statement() { - JSParseNode *pn; + ParseNode *pn; JS_CHECK_RECURSION(context, return NULL); @@ -4492,15 +4482,15 @@ Parser::statement() pn = TernaryNode::create(tc); if (!pn) return NULL; - JSParseNode *pn1 = condition(); + ParseNode *pn1 = condition(); if (!pn1) return NULL; - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_IF, -1); - JSParseNode *pn2 = statement(); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_IF, -1); + ParseNode *pn2 = statement(); if (!pn2) return NULL; - JSParseNode *pn3; + ParseNode *pn3; if (tokenStream.matchToken(TOK_ELSE, TSF_OPERAND)) { stmtInfo.type = STMT_ELSE; pn3 = statement(); @@ -4526,13 +4516,13 @@ Parser::statement() pn = BinaryNode::create(tc); if (!pn) return NULL; - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1); - JSParseNode *pn2 = condition(); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1); + ParseNode *pn2 = condition(); if (!pn2) return NULL; pn->pn_left = pn2; - JSParseNode *pn3 = statement(); + ParseNode *pn3 = statement(); if (!pn3) return NULL; PopStatement(tc); @@ -4546,14 +4536,14 @@ Parser::statement() pn = BinaryNode::create(tc); if (!pn) return NULL; - JSStmtInfo stmtInfo; - js_PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1); - JSParseNode *pn2 = statement(); + StmtInfo stmtInfo; + PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1); + ParseNode *pn2 = statement(); if (!pn2) return NULL; pn->pn_left = pn2; MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO); - JSParseNode *pn3 = condition(); + ParseNode *pn3 = condition(); if (!pn3) return NULL; PopStatement(tc); @@ -4592,7 +4582,7 @@ Parser::statement() return NULL; } - JSParseNode *pn2 = expr(); + ParseNode *pn2 = expr(); if (!pn2) return NULL; pn->pn_pos.end = pn2->pn_pos.end; @@ -4617,7 +4607,7 @@ Parser::statement() return NULL; if (!MatchLabel(context, &tokenStream, pn)) return NULL; - JSStmtInfo *stmt = tc->topStmt; + StmtInfo *stmt = tc->topStmt; JSAtom *label = pn->pn_atom; if (label) { for (; ; stmt = stmt->down) { @@ -4650,10 +4640,10 @@ Parser::statement() return NULL; if (!MatchLabel(context, &tokenStream, pn)) return NULL; - JSStmtInfo *stmt = tc->topStmt; + StmtInfo *stmt = tc->topStmt; JSAtom *label = pn->pn_atom; if (label) { - for (JSStmtInfo *stmt2 = NULL; ; stmt = stmt->down) { + for (StmtInfo *stmt2 = NULL; ; stmt = stmt->down) { if (!stmt) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_LABEL_NOT_FOUND); return NULL; @@ -4714,7 +4704,7 @@ Parser::statement() oldflags = tc->flags; tc->flags = oldflags & ~TCF_HAS_FUNCTION_STMT; - JSStmtInfo stmtInfo; + StmtInfo stmtInfo; if (!PushBlocklikeStatement(&stmtInfo, STMT_BLOCK, tc)) return NULL; pn = statements(); @@ -4769,7 +4759,7 @@ Parser::statement() /* Is this an E4X dagger I see before me? */ tc->flags |= TCF_FUN_HEAVYWEIGHT; - JSParseNode *pn2 = expr(); + ParseNode *pn2 = expr(); if (!pn2) return NULL; pn->setOp(JSOP_DEFXMLNS); @@ -4793,14 +4783,14 @@ Parser::statement() return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL; } -JSParseNode * +ParseNode * Parser::variables(bool inLetHead) { TokenKind tt; bool let; - JSStmtInfo *scopeStmt; + StmtInfo *scopeStmt; BindData data; - JSParseNode *pn, *pn2; + ParseNode *pn, *pn2; /* * The three options here are: @@ -4814,7 +4804,7 @@ Parser::variables(bool inLetHead) #if JS_HAS_BLOCK_SCOPE bool popScope = (inLetHead || (let && (tc->flags & TCF_IN_FOR_INIT))); - JSStmtInfo *save = tc->topStmt, *saveScope = tc->topScopeStmt; + StmtInfo *save = tc->topStmt, *saveScope = tc->topScopeStmt; #endif /* Make sure that statement set up the tree context correctly. */ @@ -4874,7 +4864,7 @@ Parser::variables(bool inLetHead) tc->topScopeStmt = saveScope->downScope; } #endif - JSParseNode *init = assignExpr(); + ParseNode *init = assignExpr(); #if JS_HAS_BLOCK_SCOPE if (popScope) { tc->topStmt = save; @@ -4886,7 +4876,7 @@ Parser::variables(bool inLetHead) return NULL; UndominateInitializers(pn2, init->pn_pos.end, tc); - pn2 = JSParseNode::newBinaryOrAppend(TOK_ASSIGN, JSOP_NOP, pn2, init, tc); + pn2 = ParseNode::newBinaryOrAppend(TOK_ASSIGN, JSOP_NOP, pn2, init, tc); if (!pn2) return NULL; pn->append(pn2); @@ -4921,7 +4911,7 @@ Parser::variables(bool inLetHead) tc->topScopeStmt = saveScope->downScope; } #endif - JSParseNode *init = assignExpr(); + ParseNode *init = assignExpr(); #if JS_HAS_BLOCK_SCOPE if (popScope) { tc->topStmt = save; @@ -4970,12 +4960,12 @@ bad_var_init: return NULL; } -JSParseNode * +ParseNode * Parser::expr() { - JSParseNode *pn = assignExpr(); + ParseNode *pn = assignExpr(); if (pn && tokenStream.matchToken(TOK_COMMA)) { - JSParseNode *pn2 = ListNode::create(tc); + ParseNode *pn2 = ListNode::create(tc); if (!pn2) return NULL; pn2->pn_pos.begin = pn->pn_pos.begin; @@ -5006,11 +4996,11 @@ Parser::expr() * speedup. These macros help avoid some boilerplate code. */ #define BEGIN_EXPR_PARSER(name) \ - JS_ALWAYS_INLINE JSParseNode * \ + JS_ALWAYS_INLINE ParseNode * \ Parser::name##i() #define END_EXPR_PARSER(name) \ - JS_NEVER_INLINE JSParseNode * \ + JS_NEVER_INLINE ParseNode * \ Parser::name##n() { \ return name##i(); \ } @@ -5018,7 +5008,7 @@ Parser::expr() BEGIN_EXPR_PARSER(mulExpr1) { TokenKind tt; - JSParseNode *pn = unaryExpr(); + ParseNode *pn = unaryExpr(); /* * Note: unlike addExpr1() et al, we use getToken() here instead of @@ -5028,7 +5018,7 @@ BEGIN_EXPR_PARSER(mulExpr1) while (pn && ((tt = tokenStream.getToken()) == TOK_STAR || tt == TOK_DIVOP)) { tt = tokenStream.currentToken().type; JSOp op = tokenStream.currentToken().t_op; - pn = JSParseNode::newBinaryOrAppend(tt, op, pn, unaryExpr(), tc); + pn = ParseNode::newBinaryOrAppend(tt, op, pn, unaryExpr(), tc); } return pn; } @@ -5036,11 +5026,11 @@ END_EXPR_PARSER(mulExpr1) BEGIN_EXPR_PARSER(addExpr1) { - JSParseNode *pn = mulExpr1i(); + ParseNode *pn = mulExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_PLUS, TOK_MINUS)) { TokenKind tt = tokenStream.currentToken().type; JSOp op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB; - pn = JSParseNode::newBinaryOrAppend(tt, op, pn, mulExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(tt, op, pn, mulExpr1n(), tc); } return pn; } @@ -5048,10 +5038,10 @@ END_EXPR_PARSER(addExpr1) BEGIN_EXPR_PARSER(shiftExpr1) { - JSParseNode *pn = addExpr1i(); + ParseNode *pn = addExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_SHOP)) { JSOp op = tokenStream.currentToken().t_op; - pn = JSParseNode::newBinaryOrAppend(TOK_SHOP, op, pn, addExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_SHOP, op, pn, addExpr1n(), tc); } return pn; } @@ -5067,7 +5057,7 @@ BEGIN_EXPR_PARSER(relExpr1) */ tc->flags &= ~TCF_IN_FOR_INIT; - JSParseNode *pn = shiftExpr1i(); + ParseNode *pn = shiftExpr1i(); while (pn && (tokenStream.isCurrentTokenType(TOK_RELOP) || /* @@ -5078,7 +5068,7 @@ BEGIN_EXPR_PARSER(relExpr1) tokenStream.isCurrentTokenType(TOK_INSTANCEOF))) { TokenKind tt = tokenStream.currentToken().type; JSOp op = tokenStream.currentToken().t_op; - pn = JSParseNode::newBinaryOrAppend(tt, op, pn, shiftExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(tt, op, pn, shiftExpr1n(), tc); } /* Restore previous state of inForInit flag. */ tc->flags |= inForInitFlag; @@ -5089,10 +5079,10 @@ END_EXPR_PARSER(relExpr1) BEGIN_EXPR_PARSER(eqExpr1) { - JSParseNode *pn = relExpr1i(); + ParseNode *pn = relExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_EQOP)) { JSOp op = tokenStream.currentToken().t_op; - pn = JSParseNode::newBinaryOrAppend(TOK_EQOP, op, pn, relExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_EQOP, op, pn, relExpr1n(), tc); } return pn; } @@ -5100,55 +5090,55 @@ END_EXPR_PARSER(eqExpr1) BEGIN_EXPR_PARSER(bitAndExpr1) { - JSParseNode *pn = eqExpr1i(); + ParseNode *pn = eqExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_BITAND)) - pn = JSParseNode::newBinaryOrAppend(TOK_BITAND, JSOP_BITAND, pn, eqExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_BITAND, JSOP_BITAND, pn, eqExpr1n(), tc); return pn; } END_EXPR_PARSER(bitAndExpr1) BEGIN_EXPR_PARSER(bitXorExpr1) { - JSParseNode *pn = bitAndExpr1i(); + ParseNode *pn = bitAndExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_BITXOR)) - pn = JSParseNode::newBinaryOrAppend(TOK_BITXOR, JSOP_BITXOR, pn, bitAndExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_BITXOR, JSOP_BITXOR, pn, bitAndExpr1n(), tc); return pn; } END_EXPR_PARSER(bitXorExpr1) BEGIN_EXPR_PARSER(bitOrExpr1) { - JSParseNode *pn = bitXorExpr1i(); + ParseNode *pn = bitXorExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_BITOR)) - pn = JSParseNode::newBinaryOrAppend(TOK_BITOR, JSOP_BITOR, pn, bitXorExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_BITOR, JSOP_BITOR, pn, bitXorExpr1n(), tc); return pn; } END_EXPR_PARSER(bitOrExpr1) BEGIN_EXPR_PARSER(andExpr1) { - JSParseNode *pn = bitOrExpr1i(); + ParseNode *pn = bitOrExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_AND)) - pn = JSParseNode::newBinaryOrAppend(TOK_AND, JSOP_AND, pn, bitOrExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_AND, JSOP_AND, pn, bitOrExpr1n(), tc); return pn; } END_EXPR_PARSER(andExpr1) -JS_ALWAYS_INLINE JSParseNode * +JS_ALWAYS_INLINE ParseNode * Parser::orExpr1() { - JSParseNode *pn = andExpr1i(); + ParseNode *pn = andExpr1i(); while (pn && tokenStream.isCurrentTokenType(TOK_OR)) - pn = JSParseNode::newBinaryOrAppend(TOK_OR, JSOP_OR, pn, andExpr1n(), tc); + pn = ParseNode::newBinaryOrAppend(TOK_OR, JSOP_OR, pn, andExpr1n(), tc); return pn; } -JS_ALWAYS_INLINE JSParseNode * +JS_ALWAYS_INLINE ParseNode * Parser::condExpr1() { - JSParseNode *pn = orExpr1(); + ParseNode *pn = orExpr1(); if (pn && tokenStream.isCurrentTokenType(TOK_HOOK)) { - JSParseNode *pn1 = pn; + ParseNode *pn1 = pn; pn = TernaryNode::create(tc); if (!pn) return NULL; @@ -5160,13 +5150,13 @@ Parser::condExpr1() */ uintN oldflags = tc->flags; tc->flags &= ~TCF_IN_FOR_INIT; - JSParseNode *pn2 = assignExpr(); + ParseNode *pn2 = assignExpr(); tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS); if (!pn2) return NULL; MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND); - JSParseNode *pn3 = assignExpr(); + ParseNode *pn3 = assignExpr(); if (!pn3) return NULL; pn->pn_pos.begin = pn1->pn_pos.begin; @@ -5180,7 +5170,7 @@ Parser::condExpr1() } bool -Parser::setAssignmentLhsOps(JSParseNode *pn, JSOp op) +Parser::setAssignmentLhsOps(ParseNode *pn, JSOp op) { switch (pn->getKind()) { case TOK_NAME: @@ -5225,7 +5215,7 @@ Parser::setAssignmentLhsOps(JSParseNode *pn, JSOp op) return true; } -JSParseNode * +ParseNode * Parser::assignExpr() { JS_CHECK_RECURSION(context, return NULL); @@ -5235,7 +5225,7 @@ Parser::assignExpr() return returnOrYield(true); #endif - JSParseNode *pn = condExpr1(); + ParseNode *pn = condExpr1(); if (!pn) return NULL; @@ -5248,11 +5238,11 @@ Parser::assignExpr() if (!setAssignmentLhsOps(pn, op)) return NULL; - JSParseNode *rhs = assignExpr(); + ParseNode *rhs = assignExpr(); if (!rhs) return NULL; if (pn->isKind(TOK_NAME) && pn->isUsed()) { - JSDefinition *dn = pn->pn_lexdef; + Definition *dn = pn->pn_lexdef; /* * If the definition is not flagged as assigned, we must have imputed @@ -5267,12 +5257,12 @@ Parser::assignExpr() } } - return JSParseNode::newBinaryOrAppend(TOK_ASSIGN, op, pn, rhs, tc); + return ParseNode::newBinaryOrAppend(TOK_ASSIGN, op, pn, rhs, tc); } -static JSParseNode * -SetLvalKid(JSContext *cx, TokenStream *ts, JSTreeContext *tc, - JSParseNode *pn, JSParseNode *kid, const char *name) +static ParseNode * +SetLvalKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid, + const char *name) { if (!kid->isKind(TOK_NAME) && !kid->isKind(TOK_DOT) && @@ -5295,8 +5285,7 @@ SetLvalKid(JSContext *cx, TokenStream *ts, JSTreeContext *tc, static const char incop_name_str[][10] = {"increment", "decrement"}; static JSBool -SetIncOpKid(JSContext *cx, TokenStream *ts, JSTreeContext *tc, - JSParseNode *pn, JSParseNode *kid, +SetIncOpKid(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, ParseNode *kid, TokenKind tt, JSBool preorder) { JSOp op; @@ -5342,10 +5331,10 @@ SetIncOpKid(JSContext *cx, TokenStream *ts, JSTreeContext *tc, return JS_TRUE; } -JSParseNode * +ParseNode * Parser::unaryExpr() { - JSParseNode *pn, *pn2; + ParseNode *pn, *pn2; JS_CHECK_RECURSION(context, return NULL); @@ -5394,7 +5383,7 @@ Parser::unaryExpr() * returns true. Here we fold constants before checking for a call * expression, in order to rule out delete of a generator expression. */ - if (foldConstants && !js_FoldConstants(context, pn2, tc)) + if (foldConstants && !FoldConstants(context, pn2, tc)) return NULL; switch (pn2->getKind()) { case TOK_LP: @@ -5476,19 +5465,19 @@ Parser::unaryExpr() * the one or more bindings induced by V have not yet been created. */ class CompExprTransplanter { - JSParseNode *root; - JSTreeContext *tc; + ParseNode *root; + TreeContext *tc; bool genexp; uintN adjust; uintN funcLevel; public: - CompExprTransplanter(JSParseNode *pn, JSTreeContext *tc, bool ge, uintN adj) + CompExprTransplanter(ParseNode *pn, TreeContext *tc, bool ge, uintN adj) : root(pn), tc(tc), genexp(ge), adjust(adj), funcLevel(0) { } - bool transplant(JSParseNode *pn); + bool transplant(ParseNode *pn); }; /* @@ -5509,12 +5498,12 @@ class CompExprTransplanter { * - maybeNoteGenerator() if this *did not* turn out to be a generator expression */ class GenexpGuard { - JSTreeContext *tc; + TreeContext *tc; uint32 startYieldCount; uint32 startArgumentsCount; public: - explicit GenexpGuard(JSTreeContext *tc) + explicit GenexpGuard(TreeContext *tc) : tc(tc) { if (tc->parenDepth == 0) { @@ -5527,8 +5516,8 @@ class GenexpGuard { } void endBody(); - bool checkValidBody(JSParseNode *pn); - bool maybeNoteGenerator(JSParseNode *pn); + bool checkValidBody(ParseNode *pn); + bool maybeNoteGenerator(ParseNode *pn); }; void @@ -5545,10 +5534,10 @@ GenexpGuard::endBody() * generator expression. */ bool -GenexpGuard::checkValidBody(JSParseNode *pn) +GenexpGuard::checkValidBody(ParseNode *pn) { if (tc->yieldCount > startYieldCount) { - JSParseNode *errorNode = tc->yieldNode; + ParseNode *errorNode = tc->yieldNode; if (!errorNode) errorNode = pn; tc->parser->reportErrorNumber(errorNode, JSREPORT_ERROR, JSMSG_BAD_GENEXP_BODY, js_yield_str); @@ -5556,7 +5545,7 @@ GenexpGuard::checkValidBody(JSParseNode *pn) } if (tc->argumentsCount > startArgumentsCount) { - JSParseNode *errorNode = tc->argumentsNode; + ParseNode *errorNode = tc->argumentsNode; if (!errorNode) errorNode = pn; tc->parser->reportErrorNumber(errorNode, JSREPORT_ERROR, JSMSG_BAD_GENEXP_BODY, js_arguments_str); @@ -5574,7 +5563,7 @@ GenexpGuard::checkValidBody(JSParseNode *pn) * generator expression. */ bool -GenexpGuard::maybeNoteGenerator(JSParseNode *pn) +GenexpGuard::maybeNoteGenerator(ParseNode *pn) { if (tc->yieldCount > 0) { tc->flags |= TCF_FUN_IS_GENERATOR; @@ -5600,7 +5589,7 @@ GenexpGuard::maybeNoteGenerator(JSParseNode *pn) * upvar-frame-skip count. */ static bool -BumpStaticLevel(JSParseNode *pn, JSTreeContext *tc) +BumpStaticLevel(ParseNode *pn, TreeContext *tc) { if (!pn->pn_cookie.isFree()) { uintN level = pn->pn_cookie.level() + 1; @@ -5618,7 +5607,7 @@ BumpStaticLevel(JSParseNode *pn, JSTreeContext *tc) } static void -AdjustBlockId(JSParseNode *pn, uintN adjust, JSTreeContext *tc) +AdjustBlockId(ParseNode *pn, uintN adjust, TreeContext *tc) { JS_ASSERT(pn->isArity(PN_LIST) || pn->isArity(PN_FUNC) || pn->isArity(PN_NAME)); pn->pn_blockid += adjust; @@ -5627,14 +5616,14 @@ AdjustBlockId(JSParseNode *pn, uintN adjust, JSTreeContext *tc) } bool -CompExprTransplanter::transplant(JSParseNode *pn) +CompExprTransplanter::transplant(ParseNode *pn) { if (!pn) return true; switch (pn->getArity()) { case PN_LIST: - for (JSParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { + for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { if (!transplant(pn2)) return false; } @@ -5677,13 +5666,13 @@ CompExprTransplanter::transplant(JSParseNode *pn) * the definition or expression of the function and not the static level * of the function's body. */ - JSFunctionBox *funbox = pn->pn_funbox; + FunctionBox *funbox = pn->pn_funbox; funbox->level = tc->staticLevel + funcLevel; if (++funcLevel == 1 && genexp) { - JSFunctionBox *parent = tc->funbox; + FunctionBox *parent = tc->funbox; - JSFunctionBox **funboxp = &tc->parent->functionList; + FunctionBox **funboxp = &tc->parent->functionList; while (*funboxp != funbox) funboxp = &(*funboxp)->siblings; *funboxp = funbox->siblings; @@ -5709,7 +5698,7 @@ CompExprTransplanter::transplant(JSParseNode *pn) JS_ASSERT(!pn->isOp(JSOP_NOP)); JS_ASSERT(pn->pn_cookie.isFree()); - JSDefinition *dn = pn->pn_lexdef; + Definition *dn = pn->pn_lexdef; JS_ASSERT(dn->isDefn()); /* @@ -5729,7 +5718,7 @@ CompExprTransplanter::transplant(JSParseNode *pn) JSAtom *atom = pn->pn_atom; #ifdef DEBUG - JSStmtInfo *stmt = js_LexicalLookup(tc, atom, NULL); + StmtInfo *stmt = LexicalLookup(tc, atom, NULL); JS_ASSERT(!stmt || stmt != tc->topStmt); #endif if (genexp && !dn->isOp(JSOP_CALLEE)) { @@ -5744,7 +5733,7 @@ CompExprTransplanter::transplant(JSParseNode *pn) * generator) a use of a new placeholder in the generator's * lexdeps. */ - JSDefinition *dn2 = MakePlaceholder(pn, tc); + Definition *dn2 = MakePlaceholder(pn, tc); if (!dn2) return false; dn2->pn_pos = root->pn_pos; @@ -5753,8 +5742,8 @@ CompExprTransplanter::transplant(JSParseNode *pn) * Change all uses of |dn| that lie within the generator's * |yield| expression into uses of dn2. */ - JSParseNode **pnup = &dn->dn_uses; - JSParseNode *pnu; + ParseNode **pnup = &dn->dn_uses; + ParseNode *pnu; while ((pnu = *pnup) != NULL && pnu->pn_pos >= root->pn_pos) { pnu->pn_lexdef = dn2; dn2->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS; @@ -5803,13 +5792,13 @@ CompExprTransplanter::transplant(JSParseNode *pn) * comprehension or generator expression, with a unary node as the body of the * (possibly nested) for-loop, initialized by |type, op, kid|. */ -JSParseNode * -Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, +ParseNode * +Parser::comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp, TokenKind type, JSOp op) { uintN adjust; - JSParseNode *pn, *pn2, *pn3, **pnp; - JSStmtInfo stmtInfo; + ParseNode *pn, *pn2, *pn3, **pnp; + StmtInfo stmtInfo; BindData data; TokenKind tt; @@ -5833,7 +5822,7 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, * this array comprehension. Our caller in primaryExpr, the TOK_LB case * aka the array initialiser case, has passed the blockid to claim for * the comprehension's block scope. We allocate that id or one above it - * here, by calling js_PushLexicalScope. + * here, by calling PushLexicalScope. * * In the case of a comprehension expression that has nested blocks * (e.g., let expressions), we will allocate a higher blockid but then @@ -5922,7 +5911,7 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, } MUST_MATCH_TOKEN(TOK_IN, JSMSG_IN_AFTER_FOR_NAME); - JSParseNode *pn4 = expr(); + ParseNode *pn4 = expr(); if (!pn4) return NULL; MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL); @@ -5972,7 +5961,7 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, * Synthesize a declaration. Every definition must appear in the parse * tree in order for ComprehensionTranslator to work. */ - JSParseNode *vars = ListNode::create(tc); + ParseNode *vars = ListNode::create(tc); if (!vars) return NULL; vars->setOp(JSOP_NOP); @@ -5987,7 +5976,7 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, if (!pn3) return NULL; - pn2->pn_left = TernaryNode::create(TOK_IN, JSOP_NOP, vars, pn3, pn4, tc); + pn2->pn_left = new_(TOK_IN, JSOP_NOP, vars, pn3, pn4); if (!pn2->pn_left) return NULL; *pnp = pn2; @@ -6034,11 +6023,11 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, * the first |in| in the chain of |for| heads. Instead, a generator expression * is merely sugar for a generator function expression and its application. */ -JSParseNode * -Parser::generatorExpr(JSParseNode *kid) +ParseNode * +Parser::generatorExpr(ParseNode *kid) { /* Create a |yield| node for |kid|. */ - JSParseNode *pn = UnaryNode::create(tc); + ParseNode *pn = UnaryNode::create(tc); if (!pn) return NULL; pn->setKind(TOK_YIELD); @@ -6049,7 +6038,7 @@ Parser::generatorExpr(JSParseNode *kid) pn->pn_hidden = true; /* Make a new node for the desugared generator function. */ - JSParseNode *genfn = FunctionNode::create(tc); + ParseNode *genfn = FunctionNode::create(tc); if (!genfn) return NULL; genfn->setKind(TOK_FUNCTION); @@ -6058,12 +6047,12 @@ Parser::generatorExpr(JSParseNode *kid) genfn->pn_dflags = PND_FUNARG; { - JSTreeContext *outertc = tc; - JSTreeContext gentc(tc->parser); + TreeContext *outertc = tc; + TreeContext gentc(tc->parser); if (!gentc.init(context)) return NULL; - JSFunctionBox *funbox = EnterFunction(genfn, &gentc); + FunctionBox *funbox = EnterFunction(genfn, &gentc); if (!funbox) return NULL; @@ -6093,7 +6082,7 @@ Parser::generatorExpr(JSParseNode *kid) genfn->pn_funbox = funbox; genfn->pn_blockid = gentc.bodyid; - JSParseNode *body = comprehensionTail(pn, outertc->blockid(), true); + ParseNode *body = comprehensionTail(pn, outertc->blockid(), true); if (!body) return NULL; JS_ASSERT(!genfn->pn_body); @@ -6109,7 +6098,7 @@ Parser::generatorExpr(JSParseNode *kid) * Our result is a call expression that invokes the anonymous generator * function object. */ - JSParseNode *result = ListNode::create(tc); + ParseNode *result = ListNode::create(tc); if (!result) return NULL; result->setKind(TOK_LP); @@ -6125,7 +6114,7 @@ static const char js_generator_str[] = "generator"; #endif /* JS_HAS_GENERATORS */ JSBool -Parser::argumentList(JSParseNode *listNode) +Parser::argumentList(ParseNode *listNode) { if (tokenStream.matchToken(TOK_RP, TSF_OPERAND)) return JS_TRUE; @@ -6134,7 +6123,7 @@ Parser::argumentList(JSParseNode *listNode) bool arg0 = true; do { - JSParseNode *argNode = assignExpr(); + ParseNode *argNode = assignExpr(); if (!argNode) return JS_FALSE; if (arg0) @@ -6179,13 +6168,13 @@ Parser::argumentList(JSParseNode *listNode) } /* Check for an immediately-applied (new'ed) lambda and clear PND_FUNARG. */ -static JSParseNode * -CheckForImmediatelyAppliedLambda(JSParseNode *pn) +static ParseNode * +CheckForImmediatelyAppliedLambda(ParseNode *pn) { if (pn->isKind(TOK_FUNCTION)) { JS_ASSERT(pn->isArity(PN_FUNC)); - JSFunctionBox *funbox = pn->pn_funbox; + FunctionBox *funbox = pn->pn_funbox; JS_ASSERT((funbox->function())->flags & JSFUN_LAMBDA); if (!(funbox->tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME))) pn->pn_dflags &= ~PND_FUNARG; @@ -6193,10 +6182,10 @@ CheckForImmediatelyAppliedLambda(JSParseNode *pn) return pn; } -JSParseNode * +ParseNode * Parser::memberExpr(JSBool allowCallSyntax) { - JSParseNode *pn, *pn2, *pn3; + ParseNode *pn, *pn2, *pn3; JS_CHECK_RECURSION(context, return NULL); @@ -6228,16 +6217,9 @@ Parser::memberExpr(JSBool allowCallSyntax) return NULL; if (pn->isKind(TOK_ANYNAME) || pn->isKind(TOK_AT) || pn->isKind(TOK_DBLCOLON)) { - pn2 = NewOrRecycledNode(tc); - if (!pn2) + pn = new_(TOK_UNARYOP, JSOP_XMLNAME, pn->pn_pos, pn); + if (!pn) return NULL; - pn2->setKind(TOK_UNARYOP); - pn2->pn_pos = pn->pn_pos; - pn2->setOp(JSOP_XMLNAME); - pn2->setArity(PN_UNARY); - pn2->setInParens(false); - pn2->pn_kid = pn; - pn = pn2; } } @@ -6250,11 +6232,11 @@ Parser::memberExpr(JSBool allowCallSyntax) tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME); /* Treat filters as 'with' statements for name deoptimization. */ - JSParseNode *oldWith = tc->innermostWith; - JSStmtInfo stmtInfo; + ParseNode *oldWith = tc->innermostWith; + StmtInfo stmtInfo; if (tt == TOK_LP) { tc->innermostWith = pn; - js_PushStatement(tc, &stmtInfo, STMT_WITH, -1); + PushStatement(tc, &stmtInfo, STMT_WITH, -1); } pn3 = primaryExpr(tt, JS_TRUE); @@ -6271,7 +6253,7 @@ Parser::memberExpr(JSBool allowCallSyntax) pn2->setOp(JSOP_GETPROP); pn2->pn_expr = pn; pn2->pn_atom = pn3->pn_atom; - RecycleTree(pn3, tc); + freeTree(pn3); } else { if (tt == TOK_LP) { pn2->setKind(TOK_FILTER); @@ -6412,11 +6394,11 @@ Parser::memberExpr(JSBool allowCallSyntax) return pn; } -JSParseNode * +ParseNode * Parser::bracketedExpr() { uintN oldflags; - JSParseNode *pn; + ParseNode *pn; /* * Always accept the 'in' operator in a parenthesized expression, @@ -6432,12 +6414,10 @@ Parser::bracketedExpr() #if JS_HAS_XML_SUPPORT -JSParseNode * +ParseNode * Parser::endBracketedExpr() { - JSParseNode *pn; - - pn = bracketedExpr(); + ParseNode *pn = bracketedExpr(); if (!pn) return NULL; @@ -6496,13 +6476,13 @@ Parser::endBracketedExpr() * We hoist the :: match into callers of QualifiedSuffix, in order to tweak * PropertySelector vs. Identifier pn_arity, pn_op, and other members. */ -JSParseNode * +ParseNode * Parser::propertySelector() { DebugOnly tp = &tokenStream.currentToken(); JS_ASSERT(tp->type == TOK_STAR || tp->type == TOK_NAME); - JSParseNode *pn = NullaryNode::create(tc); + ParseNode *pn = NullaryNode::create(tc); if (!pn) return NULL; if (pn->isKind(TOK_STAR)) { @@ -6519,10 +6499,10 @@ Parser::propertySelector() return pn; } -JSParseNode * -Parser::qualifiedSuffix(JSParseNode *pn) +ParseNode * +Parser::qualifiedSuffix(ParseNode *pn) { - JSParseNode *pn2, *pn3; + ParseNode *pn2, *pn3; TokenKind tt; JS_ASSERT(tokenStream.currentToken().type == TOK_DBLCOLON); @@ -6564,13 +6544,13 @@ Parser::qualifiedSuffix(JSParseNode *pn) return pn2; } -JSParseNode * +ParseNode * Parser::qualifiedIdentifier() { DebugOnly tp = &tokenStream.currentToken(); JS_ASSERT(tp->type == TOK_STAR || tp->type == TOK_NAME); - JSParseNode *pn = propertySelector(); + ParseNode *pn = propertySelector(); if (!pn) return NULL; if (tokenStream.matchToken(TOK_DBLCOLON)) { @@ -6581,10 +6561,10 @@ Parser::qualifiedIdentifier() return pn; } -JSParseNode * +ParseNode * Parser::attributeIdentifier() { - JSParseNode *pn, *pn2; + ParseNode *pn, *pn2; TokenKind tt; JS_ASSERT(tokenStream.currentToken().type == TOK_AT); @@ -6610,10 +6590,10 @@ Parser::attributeIdentifier() /* * Make a TOK_LC unary node whose pn_kid is an expression. */ -JSParseNode * +ParseNode * Parser::xmlExpr(JSBool inTag) { - JSParseNode *pn, *pn2; + ParseNode *pn, *pn2; JS_ASSERT(tokenStream.currentToken().type == TOK_LC); pn = UnaryNode::create(tc); @@ -6645,10 +6625,10 @@ Parser::xmlExpr(JSBool inTag) * parse tree to XML, we preserve a TOK_XMLSPACE node only if it's the sole * child of a container tag. */ -JSParseNode * +ParseNode * Parser::xmlAtomNode() { - JSParseNode *pn = NullaryNode::create(tc); + ParseNode *pn = NullaryNode::create(tc); if (!pn) return NULL; const Token &tok = tokenStream.currentToken(); @@ -6674,10 +6654,10 @@ Parser::xmlAtomNode() * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME; if PN_UNARY, pn_type * will be TOK_LC. */ -JSParseNode * +ParseNode * Parser::xmlNameExpr() { - JSParseNode *pn, *pn2, *list; + ParseNode *pn, *pn2, *list; TokenKind tt; pn = list = NULL; @@ -6741,10 +6721,10 @@ Parser::xmlNameExpr() * PN_LIST, pn_type will be tagtype. If PN_UNARY, pn_type will be TOK_LC and * we parsed exactly one expression. */ -JSParseNode * +ParseNode * Parser::xmlTagContent(TokenKind tagtype, JSAtom **namep) { - JSParseNode *pn, *pn2, *list; + ParseNode *pn, *pn2, *list; TokenKind tt; pn = xmlNameExpr(); @@ -6814,7 +6794,7 @@ Parser::xmlTagContent(TokenKind tagtype, JSAtom **namep) * that opens the end tag for the container. */ JSBool -Parser::xmlElementContent(JSParseNode *pn) +Parser::xmlElementContent(ParseNode *pn) { tokenStream.setXMLTagMode(false); for (;;) { @@ -6825,7 +6805,7 @@ Parser::xmlElementContent(JSParseNode *pn) JSAtom *textAtom = tokenStream.currentToken().atom(); if (textAtom) { /* Non-zero-length XML text scanned. */ - JSParseNode *pn2 = xmlAtomNode(); + ParseNode *pn2 = xmlAtomNode(); if (!pn2) return JS_FALSE; pn->pn_pos.end = pn2->pn_pos.end; @@ -6837,7 +6817,7 @@ Parser::xmlElementContent(JSParseNode *pn) if (tt == TOK_XMLETAGO) break; - JSParseNode *pn2; + ParseNode *pn2; if (tt == TOK_LC) { pn2 = xmlExpr(JS_FALSE); pn->pn_xflags |= PNX_CANTFOLD; @@ -6866,10 +6846,10 @@ Parser::xmlElementContent(JSParseNode *pn) /* * Return a PN_LIST node containing an XML or XMLList Initialiser. */ -JSParseNode * +ParseNode * Parser::xmlElementOrList(JSBool allowList) { - JSParseNode *pn, *pn2, *list; + ParseNode *pn, *pn2, *list; TokenKind tt; JSAtom *startAtom, *endAtom; @@ -6899,7 +6879,7 @@ Parser::xmlElementOrList(JSBool allowList) /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */ if (pn2->isKind(TOK_XMLSTAGO)) { pn->makeEmpty(); - RecycleTree(pn, tc); + freeTree(pn); pn = pn2; } else { JS_ASSERT(pn2->isKind(TOK_XMLNAME) || @@ -7003,7 +6983,7 @@ Parser::xmlElementOrList(JSBool allowList) return pn; } -JSParseNode * +ParseNode * Parser::xmlElementOrListRoot(JSBool allowList) { /* @@ -7014,12 +6994,12 @@ Parser::xmlElementOrListRoot(JSBool allowList) */ bool hadXML = tokenStream.hasXML(); tokenStream.setXML(true); - JSParseNode *pn = xmlElementOrList(allowList); + ParseNode *pn = xmlElementOrList(allowList); tokenStream.setXML(hadXML); return pn; } -JSParseNode * +ParseNode * Parser::parseXMLText(JSObject *chain, bool allowList) { /* @@ -7027,7 +7007,7 @@ Parser::parseXMLText(JSObject *chain, bool allowList) * lightweight function activation, or if its scope chain doesn't match * the one passed to us. */ - JSTreeContext xmltc(this); + TreeContext xmltc(this); if (!xmltc.init(context)) return NULL; xmltc.setScopeChain(chain); @@ -7036,7 +7016,7 @@ Parser::parseXMLText(JSObject *chain, bool allowList) tokenStream.setXMLOnlyMode(); TokenKind tt = tokenStream.getToken(TSF_OPERAND); - JSParseNode *pn; + ParseNode *pn; if (tt != TOK_XMLSTAGO) { reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_XML_MARKUP); pn = NULL; @@ -7072,11 +7052,11 @@ Parser::parseXMLText(JSObject *chain, bool allowList) * loop iterates more than once only in crazy cases. */ static inline bool -BlockIdInScope(uintN blockid, JSTreeContext *tc) +BlockIdInScope(uintN blockid, TreeContext *tc) { if (blockid > tc->blockid()) return false; - for (JSStmtInfo *stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) { + for (StmtInfo *stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) { if (stmt->blockid == blockid) return true; } @@ -7084,10 +7064,10 @@ BlockIdInScope(uintN blockid, JSTreeContext *tc) } #endif -JSParseNode * +ParseNode * Parser::primaryExpr(TokenKind tt, JSBool afterDot) { - JSParseNode *pn, *pn2, *pn3; + ParseNode *pn, *pn2, *pn3; JSOp op; JS_CHECK_RECURSION(context, return NULL); @@ -7205,7 +7185,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) * where is the index of array's stack slot. */ if (index == 0 && pn->pn_count != 0 && tokenStream.matchToken(TOK_FOR)) { - JSParseNode *pnexp, *pntop; + ParseNode *pnexp, *pntop; /* Relabel pn as an array comprehension node. */ pn->setKind(TOK_ARRAYCOMP); @@ -7237,7 +7217,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) case TOK_LC: { - JSParseNode *pnval; + ParseNode *pnval; /* * A map from property names we've seen thus far to a mask of property @@ -7304,7 +7284,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) /* NB: Getter function in { get x(){} } is unnamed. */ pn2 = functionDef(NULL, op == JSOP_GETTER ? Getter : Setter, Expression); - pn2 = JSParseNode::newBinaryOrAppend(TOK_COLON, op, pn3, pn2, tc); + pn2 = ParseNode::newBinaryOrAppend(TOK_COLON, op, pn3, pn2, tc); goto skip; } case TOK_STRING: @@ -7359,7 +7339,7 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) #endif } - pn2 = JSParseNode::newBinaryOrAppend(TOK_COLON, op, pn3, pnval, tc); + pn2 = ParseNode::newBinaryOrAppend(TOK_COLON, op, pn3, pnval, tc); skip: if (!pn2) return NULL; @@ -7559,10 +7539,10 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) tc->countArgumentsUse(pn); } - JSStmtInfo *stmt = js_LexicalLookup(tc, pn->pn_atom, NULL); + StmtInfo *stmt = LexicalLookup(tc, pn->pn_atom, NULL); MultiDeclRange mdl = tc->decls.lookupMulti(pn->pn_atom); - JSDefinition *dn; + Definition *dn; if (!mdl.empty()) { dn = mdl.front(); @@ -7714,11 +7694,11 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) return pn; } -JSParseNode * +ParseNode * Parser::parenExpr(JSBool *genexp) { TokenPtr begin; - JSParseNode *pn; + ParseNode *pn; JS_ASSERT(tokenStream.currentToken().type == TOK_LP); begin = tokenStream.currentToken().pos.begin; diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 10de748819b8..f57693debc7d 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -54,32 +54,26 @@ #include "frontend/ParseMaps.h" #include "frontend/ParseNode.h" -JS_BEGIN_EXTERN_C - namespace js { struct GlobalScope { - GlobalScope(JSContext *cx, JSObject *globalObj, JSCodeGenerator *cg) + GlobalScope(JSContext *cx, JSObject *globalObj, CodeGenerator *cg) : globalObj(globalObj), cg(cg), defs(cx), names(cx) { } struct GlobalDef { JSAtom *atom; // If non-NULL, specifies the property name to add. - JSFunctionBox *funbox; // If non-NULL, function value for the property. + FunctionBox *funbox; // If non-NULL, function value for the property. // This value is only set/used if atom is non-NULL. uint32 knownSlot; // If atom is NULL, this is the known shape slot. GlobalDef() { } - GlobalDef(uint32 knownSlot) - : atom(NULL), knownSlot(knownSlot) - { } - GlobalDef(JSAtom *atom, JSFunctionBox *box) : - atom(atom), funbox(box) - { } + GlobalDef(uint32 knownSlot) : atom(NULL), knownSlot(knownSlot) { } + GlobalDef(JSAtom *atom, FunctionBox *box) : atom(atom), funbox(box) { } }; JSObject *globalObj; - JSCodeGenerator *cg; + CodeGenerator *cg; /* * This is the table of global names encountered during parsing. Each @@ -103,7 +97,7 @@ namespace js { enum FunctionSyntaxKind { Expression, Statement }; -struct Parser : private js::AutoGCRooter +struct Parser : private AutoGCRooter { JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */ void *tempFreeList[NUM_TEMP_FREELISTS]; @@ -112,13 +106,13 @@ struct Parser : private js::AutoGCRooter JSPrincipals *principals; /* principals associated with source */ StackFrame *const callerFrame; /* scripted caller frame for eval and dbgapi */ JSObject *const callerVarObj; /* callerFrame's varObj */ - JSParseNode *nodeList; /* list of recyclable parse-node structs */ + ParseNodeAllocator allocator; uint32 functionCount; /* number of functions in current unit */ - JSObjectBox *traceListHead; /* list of parsed object for GC tracing */ - JSTreeContext *tc; /* innermost tree context (stack-allocated) */ + ObjectBox *traceListHead; /* list of parsed object for GC tracing */ + TreeContext *tc; /* innermost tree context (stack-allocated) */ /* Root atoms and objects allocated for the parsed tree. */ - js::AutoKeepAtoms keepAtoms; + AutoKeepAtoms keepAtoms; /* Perform constant-folding; must be true when interfacing with the emitter. */ bool foldConstants; @@ -126,9 +120,9 @@ struct Parser : private js::AutoGCRooter Parser(JSContext *cx, JSPrincipals *prin = NULL, StackFrame *cfp = NULL, bool fold = true); ~Parser(); - friend void js::AutoGCRooter::trace(JSTracer *trc); - friend struct ::JSTreeContext; - friend struct Compiler; + friend void AutoGCRooter::trace(JSTracer *trc); + friend struct TreeContext; + friend struct BytecodeCompiler; /* * Initialize a parser. Parameters are passed on to init tokenStream. @@ -149,48 +143,61 @@ struct Parser : private js::AutoGCRooter /* * Parse a top-level JS script. */ - JSParseNode *parse(JSObject *chain); + ParseNode *parse(JSObject *chain); #if JS_HAS_XML_SUPPORT - JSParseNode *parseXMLText(JSObject *chain, bool allowList); + ParseNode *parseXMLText(JSObject *chain, bool allowList); #endif /* * Allocate a new parsed object or function container from cx->tempPool. */ - JSObjectBox *newObjectBox(JSObject *obj); + ObjectBox *newObjectBox(JSObject *obj); - JSFunctionBox *newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc); + FunctionBox *newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc); /* * Create a new function object given tree context (tc) and a name (which * is optional if this is a function expression). */ - JSFunction *newFunction(JSTreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind); + JSFunction *newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind); /* * Analyze the tree of functions nested within a single compilation unit, * starting at funbox, recursively walking its kids, then following its * siblings, their kids, etc. */ - bool analyzeFunctions(JSTreeContext *tc); - void cleanFunctionList(JSFunctionBox **funbox); - bool markFunArgs(JSFunctionBox *funbox); - void markExtensibleScopeDescendants(JSFunctionBox *funbox, bool hasExtensibleParent); - void setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags); + bool analyzeFunctions(TreeContext *tc); + void cleanFunctionList(FunctionBox **funbox); + bool markFunArgs(FunctionBox *funbox); + void markExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent); + void setFunctionKinds(FunctionBox *funbox, uint32 *tcflags); void trace(JSTracer *trc); /* * Report a parse (compile) error. */ - inline bool reportErrorNumber(JSParseNode *pn, uintN flags, uintN errorNumber, ...); + inline bool reportErrorNumber(ParseNode *pn, uintN flags, uintN errorNumber, ...); -private: + private: + void *allocParseNode(size_t size) { + JS_ASSERT(size == sizeof(ParseNode)); + return allocator.allocNode(); + } + + public: + ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); } + void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); } + + /* new_ methods for creating parse nodes. These report OOM on context. */ + JS_DECLARE_NEW_METHODS(allocParseNode, inline) + + private: /* * JS parsers, from lowest to highest precedence. * - * Each parser must be called during the dynamic scope of a JSTreeContext + * Each parser must be called during the dynamic scope of a TreeContext * object, pointed to by this->tc. * * Each returns a parse node tree or null on error. @@ -203,87 +210,87 @@ private: * Some parsers have two versions: an always-inlined version (with an 'i' * suffix) and a never-inlined version (with an 'n' suffix). */ - JSParseNode *functionStmt(); - JSParseNode *functionExpr(); - JSParseNode *statements(); - JSParseNode *statement(); - JSParseNode *switchStatement(); - JSParseNode *forStatement(); - JSParseNode *tryStatement(); - JSParseNode *withStatement(); + ParseNode *functionStmt(); + ParseNode *functionExpr(); + ParseNode *statements(); + ParseNode *statement(); + ParseNode *switchStatement(); + ParseNode *forStatement(); + ParseNode *tryStatement(); + ParseNode *withStatement(); #if JS_HAS_BLOCK_SCOPE - JSParseNode *letStatement(); + ParseNode *letStatement(); #endif - JSParseNode *expressionStatement(); - JSParseNode *variables(bool inLetHead); - JSParseNode *expr(); - JSParseNode *assignExpr(); - JSParseNode *condExpr1(); - JSParseNode *orExpr1(); - JSParseNode *andExpr1i(); - JSParseNode *andExpr1n(); - JSParseNode *bitOrExpr1i(); - JSParseNode *bitOrExpr1n(); - JSParseNode *bitXorExpr1i(); - JSParseNode *bitXorExpr1n(); - JSParseNode *bitAndExpr1i(); - JSParseNode *bitAndExpr1n(); - JSParseNode *eqExpr1i(); - JSParseNode *eqExpr1n(); - JSParseNode *relExpr1i(); - JSParseNode *relExpr1n(); - JSParseNode *shiftExpr1i(); - JSParseNode *shiftExpr1n(); - JSParseNode *addExpr1i(); - JSParseNode *addExpr1n(); - JSParseNode *mulExpr1i(); - JSParseNode *mulExpr1n(); - JSParseNode *unaryExpr(); - JSParseNode *memberExpr(JSBool allowCallSyntax); - JSParseNode *primaryExpr(js::TokenKind tt, JSBool afterDot); - JSParseNode *parenExpr(JSBool *genexp = NULL); + ParseNode *expressionStatement(); + ParseNode *variables(bool inLetHead); + ParseNode *expr(); + ParseNode *assignExpr(); + ParseNode *condExpr1(); + ParseNode *orExpr1(); + ParseNode *andExpr1i(); + ParseNode *andExpr1n(); + ParseNode *bitOrExpr1i(); + ParseNode *bitOrExpr1n(); + ParseNode *bitXorExpr1i(); + ParseNode *bitXorExpr1n(); + ParseNode *bitAndExpr1i(); + ParseNode *bitAndExpr1n(); + ParseNode *eqExpr1i(); + ParseNode *eqExpr1n(); + ParseNode *relExpr1i(); + ParseNode *relExpr1n(); + ParseNode *shiftExpr1i(); + ParseNode *shiftExpr1n(); + ParseNode *addExpr1i(); + ParseNode *addExpr1n(); + ParseNode *mulExpr1i(); + ParseNode *mulExpr1n(); + ParseNode *unaryExpr(); + ParseNode *memberExpr(JSBool allowCallSyntax); + ParseNode *primaryExpr(TokenKind tt, JSBool afterDot); + ParseNode *parenExpr(JSBool *genexp = NULL); /* * Additional JS parsers. */ - bool recognizeDirectivePrologue(JSParseNode *pn, bool *isDirectivePrologueMember); + bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember); enum FunctionType { Getter, Setter, Normal }; - bool functionArguments(JSTreeContext &funtc, JSFunctionBox *funbox, JSParseNode **list); - JSParseNode *functionBody(); - JSParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind); + bool functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **list); + ParseNode *functionBody(); + ParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind); - JSParseNode *condition(); - JSParseNode *comprehensionTail(JSParseNode *kid, uintN blockid, bool isGenexp, - js::TokenKind type = js::TOK_SEMI, JSOp op = JSOP_NOP); - JSParseNode *generatorExpr(JSParseNode *kid); - JSBool argumentList(JSParseNode *listNode); - JSParseNode *bracketedExpr(); - JSParseNode *letBlock(JSBool statement); - JSParseNode *returnOrYield(bool useAssignExpr); - JSParseNode *destructuringExpr(BindData *data, js::TokenKind tt); + ParseNode *condition(); + ParseNode *comprehensionTail(ParseNode *kid, uintN blockid, bool isGenexp, + TokenKind type = TOK_SEMI, JSOp op = JSOP_NOP); + ParseNode *generatorExpr(ParseNode *kid); + JSBool argumentList(ParseNode *listNode); + ParseNode *bracketedExpr(); + ParseNode *letBlock(JSBool statement); + ParseNode *returnOrYield(bool useAssignExpr); + ParseNode *destructuringExpr(BindData *data, TokenKind tt); #if JS_HAS_XML_SUPPORT - JSParseNode *endBracketedExpr(); + ParseNode *endBracketedExpr(); - JSParseNode *propertySelector(); - JSParseNode *qualifiedSuffix(JSParseNode *pn); - JSParseNode *qualifiedIdentifier(); - JSParseNode *attributeIdentifier(); - JSParseNode *xmlExpr(JSBool inTag); - JSParseNode *xmlAtomNode(); - JSParseNode *xmlNameExpr(); - JSParseNode *xmlTagContent(js::TokenKind tagtype, JSAtom **namep); - JSBool xmlElementContent(JSParseNode *pn); - JSParseNode *xmlElementOrList(JSBool allowList); - JSParseNode *xmlElementOrListRoot(JSBool allowList); + ParseNode *propertySelector(); + ParseNode *qualifiedSuffix(ParseNode *pn); + ParseNode *qualifiedIdentifier(); + ParseNode *attributeIdentifier(); + ParseNode *xmlExpr(JSBool inTag); + ParseNode *xmlAtomNode(); + ParseNode *xmlNameExpr(); + ParseNode *xmlTagContent(TokenKind tagtype, JSAtom **namep); + JSBool xmlElementContent(ParseNode *pn); + ParseNode *xmlElementOrList(JSBool allowList); + ParseNode *xmlElementOrListRoot(JSBool allowList); #endif /* JS_HAS_XML_SUPPORT */ - bool setAssignmentLhsOps(JSParseNode *pn, JSOp op); + bool setAssignmentLhsOps(ParseNode *pn, JSOp op); }; inline bool -Parser::reportErrorNumber(JSParseNode *pn, uintN flags, uintN errorNumber, ...) +Parser::reportErrorNumber(ParseNode *pn, uintN flags, uintN errorNumber, ...) { va_list args; va_start(args, errorNumber); @@ -293,10 +300,10 @@ Parser::reportErrorNumber(JSParseNode *pn, uintN flags, uintN errorNumber, ...) } bool -CheckStrictParameters(JSContext *cx, JSTreeContext *tc); +CheckStrictParameters(JSContext *cx, TreeContext *tc); bool -DefineArg(JSParseNode *pn, JSAtom *atom, uintN i, JSTreeContext *tc); +DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc); } /* namespace js */ @@ -305,6 +312,4 @@ DefineArg(JSParseNode *pn, JSAtom *atom, uintN i, JSTreeContext *tc); */ #define TS(p) (&(p)->tokenStream) -JS_END_EXTERN_C - #endif /* Parser_h__ */ diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index e727650536a4..d3687a19ef1a 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -130,10 +130,8 @@ FindKeyword(const jschar *s, size_t length) return NULL; } -} // namespace js - JSBool -js_IsIdentifier(JSLinearString *str) +IsIdentifier(JSLinearString *str) { const jschar *chars = str->chars(); size_t length = str->length(); @@ -259,34 +257,6 @@ TokenStream::~TokenStream() # define fast_getc getc #endif -JS_FRIEND_API(int) -js_fgets(char *buf, int size, FILE *file) -{ - int n, i, c; - JSBool crflag; - - n = size - 1; - if (n < 0) - return -1; - - crflag = JS_FALSE; - for (i = 0; i < n && (c = fast_getc(file)) != EOF; i++) { - buf[i] = c; - if (c == '\n') { /* any \n ends a line */ - i++; /* keep the \n; we know there is room for \0 */ - break; - } - if (crflag) { /* \r not followed by \n ends line at the \r */ - ungetc(c, file); - break; /* and overwrite c in buf with \0 */ - } - crflag = (c == '\r'); - } - - buf[i] = '\0'; - return i; -} - JS_ALWAYS_INLINE void TokenStream::updateLineInfoForEOL() { @@ -451,8 +421,7 @@ TokenStream::TokenBuf::findEOL() } bool -TokenStream::reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN errorNumber, - va_list ap) +TokenStream::reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorNumber, va_list ap) { JSErrorReport report; char *message; @@ -579,8 +548,8 @@ TokenStream::reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN erro } bool -js::ReportStrictModeError(JSContext *cx, TokenStream *ts, JSTreeContext *tc, JSParseNode *pn, - uintN errorNumber, ...) +ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, + uintN errorNumber, ...) { JS_ASSERT(ts || tc); JS_ASSERT(cx == ts->getContext()); @@ -604,13 +573,13 @@ js::ReportStrictModeError(JSContext *cx, TokenStream *ts, JSTreeContext *tc, JSP } bool -js::ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, JSParseNode *pn, - uintN flags, uintN errorNumber, ...) +ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags, + uintN errorNumber, ...) { va_list ap; /* - * We don't accept a JSTreeContext argument, so we can't implement + * We don't accept a TreeContext argument, so we can't implement * JSREPORT_STRICT_MODE_ERROR here. Use ReportStrictModeError instead, * or do the checks in the caller and pass plain old JSREPORT_ERROR. */ @@ -953,7 +922,7 @@ TokenStream::getXMLTextOrTag(TokenKind *ttp, Token **tpp) * * https://bugzilla.mozilla.org/show_bug.cgi?id=336551 * - * The check for this is in jsparse.cpp, Compiler::compileScript. + * The check for this is in BytecodeCompiler::compileScript. */ bool TokenStream::getXMLMarkup(TokenKind *ttp, Token **tpp) @@ -2159,3 +2128,32 @@ TokenStream::getTokenInternal() return TOK_ERROR; } +} /* namespace js */ + +JS_FRIEND_API(int) +js_fgets(char *buf, int size, FILE *file) +{ + int n, i, c; + JSBool crflag; + + n = size - 1; + if (n < 0) + return -1; + + crflag = JS_FALSE; + for (i = 0; i < n && (c = fast_getc(file)) != EOF; i++) { + buf[i] = c; + if (c == '\n') { /* any \n ends a line */ + i++; /* keep the \n; we know there is room for \0 */ + break; + } + if (crflag) { /* \r not followed by \n ends line at the \r */ + ungetc(c, file); + break; /* and overwrite c in buf with \0 */ + } + crflag = (c == '\r'); + } + + buf[i] = '\0'; + return i; +} diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index fd33f6e8117c..a196caaf196e 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -152,20 +152,20 @@ enum TokenKind { TOK_LIMIT /* domain size */ }; -static inline bool +inline bool TokenKindIsXML(TokenKind tt) { return tt == TOK_AT || tt == TOK_DBLCOLON || tt == TOK_ANYNAME; } -static inline bool +inline bool TreeTypeIsXML(TokenKind tt) { return tt == TOK_XMLCOMMENT || tt == TOK_XMLCDATA || tt == TOK_XMLPI || tt == TOK_XMLELEM || tt == TOK_XMLLIST; } -static inline bool +inline bool TokenKindIsDecl(TokenKind tt) { #if JS_HAS_BLOCK_SCOPE @@ -179,29 +179,29 @@ struct TokenPtr { uint32 index; /* index of char in physical line */ uint32 lineno; /* physical line number */ - bool operator==(const TokenPtr& bptr) { + bool operator==(const TokenPtr& bptr) const { return index == bptr.index && lineno == bptr.lineno; } - bool operator!=(const TokenPtr& bptr) { + bool operator!=(const TokenPtr& bptr) const { return index != bptr.index || lineno != bptr.lineno; } - bool operator <(const TokenPtr& bptr) { + bool operator <(const TokenPtr& bptr) const { return lineno < bptr.lineno || (lineno == bptr.lineno && index < bptr.index); } - bool operator <=(const TokenPtr& bptr) { + bool operator <=(const TokenPtr& bptr) const { return lineno < bptr.lineno || (lineno == bptr.lineno && index <= bptr.index); } - bool operator >(const TokenPtr& bptr) { + bool operator >(const TokenPtr& bptr) const { return !(*this <= bptr); } - bool operator >=(const TokenPtr& bptr) { + bool operator >=(const TokenPtr& bptr) const { return !(*this < bptr); } }; @@ -210,27 +210,43 @@ struct TokenPos { TokenPtr begin; /* first character and line of token */ TokenPtr end; /* index 1 past last char, last line */ - bool operator==(const TokenPos& bpos) { + TokenPos() {} + + TokenPos(const TokenPtr &begin, const TokenPtr &end) : begin(begin), end(end) { + // Assertion temporarily disabled by jorendorff. See bug 695922. + //JS_ASSERT(begin <= end); + } + + /* Return a TokenPos that covers left, right, and anything in between. */ + static TokenPos box(const TokenPos &left, const TokenPos &right) { + // Assertions temporarily disabled by jorendorff. See bug 695922. + //JS_ASSERT(left.begin <= left.end); + //JS_ASSERT(left.end <= right.begin); + //JS_ASSERT(right.begin <= right.end); + return TokenPos(left.begin, right.end); + } + + bool operator==(const TokenPos& bpos) const { return begin == bpos.begin && end == bpos.end; } - bool operator!=(const TokenPos& bpos) { + bool operator!=(const TokenPos& bpos) const { return begin != bpos.begin || end != bpos.end; } - bool operator <(const TokenPos& bpos) { + bool operator <(const TokenPos& bpos) const { return begin < bpos.begin; } - bool operator <=(const TokenPos& bpos) { + bool operator <=(const TokenPos& bpos) const { return begin <= bpos.begin; } - bool operator >(const TokenPos& bpos) { + bool operator >(const TokenPos& bpos) const { return !(*this <= bpos); } - bool operator >=(const TokenPos& bpos) { + bool operator >=(const TokenPos& bpos) const { return !(*this < bpos); } }; @@ -417,7 +433,7 @@ class TokenStream bool hasOctalCharacterEscape() const { return flags & TSF_OCTAL_CHAR; } /* Mutators. */ - bool reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN errorNumber, va_list ap); + bool reportCompileErrorNumberVA(ParseNode *pn, uintN flags, uintN errorNumber, va_list ap); void mungeCurrentToken(TokenKind newKind) { tokens[cursor].type = newKind; } void mungeCurrentToken(JSOp newOp) { tokens[cursor].t_op = newOp; } void mungeCurrentToken(TokenKind newKind, JSOp newOp) { @@ -704,16 +720,6 @@ class TokenStream bool xml; /* see JSOPTION_XML */ }; -} /* namespace js */ - -extern void -js_CloseTokenStream(JSContext *cx, js::TokenStream *ts); - -extern JS_FRIEND_API(int) -js_fgets(char *buf, int size, FILE *file); - -namespace js { - struct KeywordInfo { const char *chars; /* C string with keyword text */ TokenKind tokentype; @@ -725,23 +731,15 @@ struct KeywordInfo { * Returns a KeywordInfo for the specified characters, or NULL if the string is * not a keyword. */ -extern const KeywordInfo * +const KeywordInfo * FindKeyword(const jschar *s, size_t length); -} // namespace js - -/* - * Friend-exported API entry point to call a mapping function on each reserved - * identifier in the scanner's keyword table. - */ -typedef void (*JSMapKeywordFun)(const char *); - /* * Check that str forms a valid JS identifier name. The function does not * check if str is a JS keyword. */ -extern JSBool -js_IsIdentifier(JSLinearString *str); +JSBool +IsIdentifier(JSLinearString *str); /* * Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error @@ -749,15 +747,13 @@ js_IsIdentifier(JSLinearString *str); */ #define JSREPORT_UC 0x100 -namespace js { - /* * Report a compile-time error by its number. Return true for a warning, false * for an error. When pn is not null, use it to report error's location. * Otherwise use ts, which must not be null. */ bool -ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, JSParseNode *pn, uintN flags, +ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags, uintN errorNumber, ...); /* @@ -770,7 +766,7 @@ ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, JSParseNode *pn, uintN * One could have ReportCompileErrorNumber recognize the * JSREPORT_STRICT_MODE_ERROR flag instead of having a separate function * like this one. However, the strict mode code flag we need to test is - * in the JSTreeContext structure for that code; we would have to change + * in the TreeContext structure for that code; we would have to change * the ~120 ReportCompileErrorNumber calls to pass the additional * argument, even though many of those sites would never use it. Using * ts's TSF_STRICT_MODE_CODE flag instead of tc's would be brittle: at some @@ -778,9 +774,12 @@ ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, JSParseNode *pn, uintN * error. */ bool -ReportStrictModeError(JSContext *cx, TokenStream *ts, JSTreeContext *tc, JSParseNode *pn, +ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn, uintN errorNumber, ...); } /* namespace js */ +extern JS_FRIEND_API(int) +js_fgets(char *buf, int size, FILE *file); + #endif /* TokenStream_h__ */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 507bb1f11147..d02996404da6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1818,7 +1818,7 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved) atom = rt->atomState.typeAtoms[JSTYPE_VOID]; if (idstr == atom) { *resolved = JS_TRUE; - return obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(), + return obj->defineProperty(cx, atom->asPropertyName(), UndefinedValue(), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY); } @@ -1889,7 +1889,6 @@ JS_PUBLIC_API(JSBool) JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) { JSRuntime *rt; - JSAtom *atom; uintN i; CHECK_REQUEST(cx); @@ -1900,9 +1899,9 @@ JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj) * Check whether we need to bind 'undefined' and define it if so. * Since ES5 15.1.1.3 undefined can't be deleted. */ - atom = rt->atomState.typeAtoms[JSTYPE_VOID]; - if (!obj->nativeContains(cx, ATOM_TO_JSID(atom)) && - !obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(), + PropertyName *name = rt->atomState.typeAtoms[JSTYPE_VOID]; + if (!obj->nativeContains(cx, ATOM_TO_JSID(name)) && + !obj->defineProperty(cx, name, UndefinedValue(), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { return JS_FALSE; @@ -3500,7 +3499,7 @@ DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value, return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, flags, tinyid); } - return obj->defineProperty(cx, id, value, getter, setter, attrs); + return obj->defineGeneric(cx, id, value, getter, setter, attrs); } JS_PUBLIC_API(JSBool) @@ -3708,7 +3707,7 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags, ? Proxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc) : Proxy::getPropertyDescriptor(cx, obj2, id, false, desc); } - if (!obj2->getAttributes(cx, id, &desc->attrs)) + if (!obj2->getGenericAttributes(cx, id, &desc->attrs)) return false; desc->getter = NULL; desc->setter = NULL; @@ -3802,7 +3801,7 @@ SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, uintN attrs, JS } JSBool ok = obj->isNative() ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs) - : obj->setAttributes(cx, id, &attrs); + : obj->setGenericAttributes(cx, id, &attrs); if (ok) *foundp = true; return ok; @@ -3895,7 +3894,7 @@ JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) CHECK_REQUEST(cx); assertSameCompartment(cx, obj, id); JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING); - return obj->setProperty(cx, id, vp, false); + return obj->setGeneric(cx, id, vp, false); } JS_PUBLIC_API(JSBool) @@ -3928,7 +3927,7 @@ JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval) CHECK_REQUEST(cx); assertSameCompartment(cx, obj, id); JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED); - return obj->deleteProperty(cx, id, rval, false); + return obj->deleteGeneric(cx, id, rval, false); } JS_PUBLIC_API(JSBool) @@ -4579,8 +4578,8 @@ CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *p AutoLastFrameCheck lfc(cx); uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT; - return Compiler::compileScript(cx, obj, NULL, principals, tcflags, - chars, length, filename, lineno, version); + return BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, chars, length, + filename, lineno, version); } extern JS_PUBLIC_API(JSScript *) @@ -4756,8 +4755,8 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals, JS_ASSERT(i <= len); len = i; uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT; - script = Compiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len, filename, 1, - cx->findVersion()); + script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len, + filename, 1, cx->findVersion()); cx->free_(buf); return script; } @@ -4856,14 +4855,16 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj, if (!fun) return NULL; - if (!Compiler::compileFunctionBody(cx, fun, principals, &bindings, - chars, length, filename, lineno, version)) { + if (!BytecodeCompiler::compileFunctionBody(cx, fun, principals, &bindings, + chars, length, filename, lineno, version)) + { return NULL; } if (obj && funAtom && - !obj->defineProperty(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun), - NULL, NULL, JSPROP_ENUMERATE)) { + !obj->defineGeneric(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun), NULL, NULL, + JSPROP_ENUMERATE)) + { return NULL; } @@ -5018,8 +5019,8 @@ EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, CHECK_REQUEST(cx); AutoLastFrameCheck lfc(cx); - JSScript *script = Compiler::compileScript(cx, obj, NULL, principals, flags, - chars, length, filename, lineno, compileVersion); + JSScript *script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, flags, chars, + length, filename, lineno, compileVersion); if (!script) return false; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index b8e2977dfd2b..fb0b7558a76f 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -481,7 +481,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, const Value &v) JS_ASSERT(!JSID_IS_VOID(idr.id())); Value tmp = v; - return obj->setProperty(cx, idr.id(), &tmp, true); + return obj->setGeneric(cx, idr.id(), &tmp, true); } #ifdef JS_TRACER @@ -541,7 +541,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index, bool strict) return 1; Value v; - if (!obj->deleteProperty(cx, idr.id(), &v, strict)) + if (!obj->deleteGeneric(cx, idr.id(), &v, strict)) return -1; return v.isTrue() ? 1 : 0; } @@ -564,13 +564,10 @@ SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length) { - Value v; - jsid id; + Value v = NumberValue(length); - v.setNumber(length); - id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); /* We don't support read-only array length yet. */ - return obj->setProperty(cx, id, &v, false); + return obj->setProperty(cx, cx->runtime->atomState.lengthAtom, &v, false); } /* @@ -596,9 +593,8 @@ static JSBool array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp) { if (!obj->isArray()) { - jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - - return obj->defineProperty(cx, lengthId, *vp, NULL, NULL, JSPROP_ENUMERATE); + return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, *vp, + NULL, NULL, JSPROP_ENUMERATE); } uint32 newlen; @@ -677,7 +673,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value jsuint index; Value junk; if (js_IdIsIndex(id, &index) && index - newlen < gap && - !obj->deleteProperty(cx, id, &junk, false)) { + !obj->deleteElement(cx, index, &junk, false)) { return false; } } @@ -903,7 +899,7 @@ array_typeOf(JSContext *cx, JSObject *obj) } static JSBool -array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +array_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { uint32 i; @@ -938,6 +934,12 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool stric return js_SetPropertyHelper(cx, obj, id, 0, vp, strict); } +static JSBool +array_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) +{ + return array_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict); +} + static JSBool array_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict) { @@ -980,7 +982,7 @@ array_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool s static JSBool array_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict) { - return array_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); + return array_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); } JSBool @@ -1005,12 +1007,9 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj) return JS_FALSE; } -namespace js { - -/* non-static for direct definition of array elements within the engine */ -JSBool -array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, - JSPropertyOp getter, StrictPropertyOp setter, uintN attrs) +static JSBool +array_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *value, + JSPropertyOp getter, StrictPropertyOp setter, uintN attrs) { if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) return JS_TRUE; @@ -1043,6 +1042,15 @@ array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, return js_DefineProperty(cx, obj, id, value, getter, setter, attrs); } +static JSBool +array_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value, + JSPropertyOp getter, StrictPropertyOp setter, uintN attrs) +{ + return array_defineGeneric(cx, obj, ATOM_TO_JSID(name), value, getter, setter, attrs); +} + +namespace js { + /* non-static for direct definition of array elements within the engine */ JSBool array_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value, @@ -1088,15 +1096,24 @@ static JSBool array_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value, PropertyOp getter, StrictPropertyOp setter, uintN attrs) { - return array_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs); + return array_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs); } static JSBool -array_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +array_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ? JSPROP_PERMANENT : JSPROP_ENUMERATE; - return JS_TRUE; + return true; +} + +static JSBool +array_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + *attrsp = (name == cx->runtime->atomState.lengthAtom) + ? JSPROP_PERMANENT + : JSPROP_ENUMERATE; + return true; } static JSBool @@ -1109,11 +1126,19 @@ array_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *at static JSBool array_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return array_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + *attrsp = JSPROP_ENUMERATE; + return true; } static JSBool -array_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +array_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +{ + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; +} + +static JSBool +array_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); return false; @@ -1129,14 +1154,12 @@ array_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *at static JSBool array_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return array_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; } -namespace js { - -/* non-static for direct deletion of array elements within the engine */ -JSBool -array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) +static JSBool +array_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { uint32 i; @@ -1160,6 +1183,14 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool return true; } +static JSBool +array_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) +{ + return array_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict); +} + +namespace js { + /* non-static for direct deletion of array elements within the engine */ JSBool array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) @@ -1184,7 +1215,7 @@ array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSB static JSBool array_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return array_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return array_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); } static void @@ -1237,7 +1268,7 @@ Class js::ArrayClass = { array_lookupProperty, array_lookupElement, array_lookupSpecial, - array_defineProperty, + array_defineGeneric, array_defineProperty, array_defineElement, array_defineSpecial, @@ -1245,19 +1276,19 @@ Class js::ArrayClass = { array_getProperty, array_getElement, array_getSpecial, - array_setProperty, + array_setGeneric, array_setProperty, array_setElement, array_setSpecial, - array_getAttributes, - array_getAttributes, + array_getGenericAttributes, + array_getPropertyAttributes, array_getElementAttributes, array_getSpecialAttributes, - array_setAttributes, - array_setAttributes, + array_setGenericAttributes, + array_setPropertyAttributes, array_setElementAttributes, array_setSpecialAttributes, - array_deleteProperty, + array_deleteGeneric, array_deleteProperty, array_deleteElement, array_deleteSpecial, @@ -1788,7 +1819,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, cons do { *tvr.addr() = *vector++; if (!js_ValueToStringId(cx, idval, idr.addr()) || - !obj->setProperty(cx, idr.id(), tvr.addr(), true)) { + !obj->setGeneric(cx, idr.id(), tvr.addr(), true)) { return JS_FALSE; } idval.getDoubleRef() += 1; @@ -2725,18 +2756,39 @@ TryReuseArrayType(JSObject *obj, JSObject *nobj) * Returns true if this is a dense array whose |count| properties starting from * |startingIndex| may be accessed (get, set, delete) directly through its * contiguous vector of elements without fear of getters, setters, etc. along - * the prototype chain. + * the prototype chain, or of enumerators requiring notification of + * modifications. */ static inline bool CanOptimizeForDenseStorage(JSObject *arr, uint32 startingIndex, uint32 count, JSContext *cx) { - JS_ASSERT(UINT32_MAX - startingIndex >= count); + /* If the desired properties overflow dense storage, we can't optimize. */ + if (UINT32_MAX - startingIndex < count) + return false; - uint32 length = startingIndex + count; - return arr->isDenseArray() && - !arr->getType(cx)->hasAllFlags(OBJECT_FLAG_NON_PACKED_ARRAY) && - !js_PrototypeHasIndexedProperties(cx, arr) && - length <= arr->getDenseArrayInitializedLength(); + /* There's no optimizing possible if it's not a dense array. */ + if (!arr->isDenseArray()) + return false; + + /* + * Don't optimize if the array might be in the midst of iteration. We + * rely on this to be able to safely move dense array elements around with + * just a memmove (see JSObject::moveDenseArrayElements), without worrying + * about updating any in-progress enumerators for properties implicitly + * deleted if a hole is moved from one location to another location not yet + * visited. See bug 690622. + * + * Another potential wrinkle: what if the enumeration is happening on an + * object which merely has |arr| on its prototype chain? It turns out this + * case can't happen, because any dense array used as the prototype of + * another object is first slowified, for type inference's sake. + */ + if (JS_UNLIKELY(arr->getType(cx)->hasAllFlags(OBJECT_FLAG_ITERATED))) + return false; + + /* Now just watch out for getters and setters along the prototype chain. */ + return !js_PrototypeHasIndexedProperties(cx, arr) && + startingIndex + count <= arr->getDenseArrayInitializedLength(); } static inline bool diff --git a/js/src/jsarray.h b/js/src/jsarray.h index fe176137e6bb..596529952cee 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -58,14 +58,6 @@ JSObject::getDenseArrayInitializedLength() return initializedLength; } -inline void -JSObject::setDenseArrayInitializedLength(uint32 length) -{ - JS_ASSERT(isDenseArray()); - JS_ASSERT(length <= getDenseArrayCapacity()); - initializedLength = length; -} - inline bool JSObject::isPackedDenseArray() { @@ -173,11 +165,11 @@ js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length); namespace js { extern JSBool -array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, - PropertyOp getter, StrictPropertyOp setter, uintN attrs); +array_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value, + PropertyOp getter, StrictPropertyOp setter, uintN attrs); extern JSBool -array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict); +array_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict); /* * Copy 'length' elements from aobj to vp. diff --git a/js/src/jsarrayinlines.h b/js/src/jsarrayinlines.h index 8336c6907c94..c30af8f79762 100644 --- a/js/src/jsarrayinlines.h +++ b/js/src/jsarrayinlines.h @@ -41,6 +41,15 @@ #define jsarrayinlines_h___ #include "jsinferinlines.h" +#include "jsobjinlines.h" + +inline void +JSObject::setDenseArrayInitializedLength(uint32 length) +{ + JS_ASSERT(isDenseArray()); + JS_ASSERT(length <= getDenseArrayCapacity()); + initializedLength = length; +} inline void JSObject::markDenseArrayNotPacked(JSContext *cx) diff --git a/js/src/jsbool.h b/js/src/jsbool.h index 07c25d9c45de..c5e857fcecbe 100644 --- a/js/src/jsbool.h +++ b/js/src/jsbool.h @@ -58,16 +58,7 @@ extern bool BooleanToStringBuffer(JSContext *cx, JSBool b, StringBuffer &sb); inline bool -BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp) -{ - if (obj.isBoolean()) { - *vp = obj.getPrimitiveThis(); - return true; - } - - extern bool BooleanGetPrimitiveValueSlow(JSContext *, JSObject &, Value *); - return BooleanGetPrimitiveValueSlow(cx, obj, vp); -} +BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp); } /* namespace js */ diff --git a/js/src/jsboolinlines.h b/js/src/jsboolinlines.h new file mode 100644 index 000000000000..c9f172593461 --- /dev/null +++ b/js/src/jsboolinlines.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is SpiderMonkey code. + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Jeff Walden (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef jsboolinlines_h___ +#define jsboolinlines_h___ + +#include "jsobjinlines.h" + +namespace js { + +inline bool +BooleanGetPrimitiveValue(JSContext *cx, JSObject &obj, Value *vp) +{ + if (obj.isBoolean()) { + *vp = obj.getPrimitiveThis(); + return true; + } + + extern bool BooleanGetPrimitiveValueSlow(JSContext *, JSObject &, Value *); + return BooleanGetPrimitiveValueSlow(cx, obj, vp); +} + +} /* namespace js */ + +#endif /* jsboolinlines_h___ */ diff --git a/js/src/jsclass.h b/js/src/jsclass.h index 27ade4415063..a2a8a8430412 100644 --- a/js/src/jsclass.h +++ b/js/src/jsclass.h @@ -193,7 +193,7 @@ typedef JSBool (* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, PropertyOp getter, StrictPropertyOp setter, uintN attrs); typedef JSBool -(* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, +(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value, PropertyOp getter, StrictPropertyOp setter, uintN attrs); typedef JSBool (* DefineElementOp)(JSContext *cx, JSObject *obj, uint32 index, const Value *value, @@ -212,7 +212,7 @@ typedef JSBool typedef JSBool (* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); typedef JSBool -(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); typedef JSBool (* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict); typedef JSBool @@ -220,7 +220,7 @@ typedef JSBool typedef JSBool (* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); typedef JSBool -(* AttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); +(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp); typedef JSBool (* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp); typedef JSBool @@ -228,7 +228,7 @@ typedef JSBool typedef JSBool (* DeleteGenericOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); typedef JSBool -(* DeleteIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +(* DeleteIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); typedef JSBool (* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict); typedef JSBool @@ -319,11 +319,11 @@ struct ObjectOps StrictElementIdOp setElement; StrictSpecialIdOp setSpecial; GenericAttributesOp getGenericAttributes; - AttributesOp getAttributes; + PropertyAttributesOp getPropertyAttributes; ElementAttributesOp getElementAttributes; SpecialAttributesOp getSpecialAttributes; GenericAttributesOp setGenericAttributes; - AttributesOp setAttributes; + PropertyAttributesOp setPropertyAttributes; ElementAttributesOp setElementAttributes; SpecialAttributesOp setSpecialAttributes; DeleteGenericOp deleteGeneric; diff --git a/js/src/jsclone.cpp b/js/src/jsclone.cpp index 4f52c677c886..5d99c953c9ad 100644 --- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -876,7 +876,7 @@ JSStructuredCloneReader::read(Value *vp) objs.popBack(); } else { Value v; - if (!startRead(&v) || !obj->defineProperty(context(), id, v)) + if (!startRead(&v) || !obj->defineGeneric(context(), id, v)) return false; } } diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 500fa87ae8c5..8ea4addfa0a8 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -406,7 +406,7 @@ JS_GetLinePCs(JSContext *cx, JSScript *script, uintN i = 0; for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { offset += SN_DELTA(sn); - JSSrcNoteType type = (JSSrcNoteType) SN_TYPE(sn); + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE || type == SRC_NEWLINE) { if (type == SRC_SETLINE) lineno = (uintN) js_GetSrcNoteOffset(sn, 0); diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index f262a7dbfcf1..a0d9223eae72 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -1241,7 +1241,7 @@ js_ReportUncaughtException(JSContext *cx) JS_ClearPendingException(cx); reportp = js_ErrorFromException(cx, exn); - /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */ + /* XXX L10N angels cry once again. see also everywhere else */ str = js_ValueToString(cx, exn); JSAutoByteString bytesStorage; if (!str) { diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 92ef58199907..664857d3080a 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -192,8 +192,8 @@ ArgumentsObject::create(JSContext *cx, uint32 argc, JSObject &callee) { JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX); - JSObject *proto; - if (!js_GetClassPrototype(cx, callee.getGlobal(), JSProto_Object, &proto)) + JSObject *proto = callee.getGlobal()->getOrCreateObjectPrototype(cx); + if (!proto) return NULL; TypeObject *type = proto->getNewType(cx); @@ -1451,10 +1451,10 @@ ResolveInterpretedFunctionPrototype(JSContext *cx, JSObject *obj) * the prototype's .constructor property is configurable, non-enumerable, * and writable. */ - if (!obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), + if (!obj->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom, ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT) || - !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), + !proto->defineProperty(cx, cx->runtime->atomState.constructorAtom, ObjectValue(*obj), JS_PropertyStub, JS_StrictPropertyStub, 0)) { return NULL; @@ -2284,9 +2284,8 @@ Function(JSContext *cx, uintN argc, Value *vp) return false; JSPrincipals *principals = PrincipalsForCompiledCode(args, cx); - bool ok = Compiler::compileFunctionBody(cx, fun, principals, &bindings, - chars, length, filename, lineno, - cx->findVersion()); + bool ok = BytecodeCompiler::compileFunctionBody(cx, fun, principals, &bindings, chars, length, + filename, lineno, cx->findVersion()); args.rval().setObject(*fun); return ok; } @@ -2582,7 +2581,7 @@ js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, Native native, if (!wasDelegate && obj->isDelegate()) obj->clearDelegate(); - if (!obj->defineProperty(cx, id, ObjectValue(*fun), gop, sop, attrs & ~JSFUN_FLAGS_MASK)) + if (!obj->defineGeneric(cx, id, ObjectValue(*fun), gop, sop, attrs & ~JSFUN_FLAGS_MASK)) return NULL; return fun; diff --git a/js/src/jsfun.h b/js/src/jsfun.h index e9a1364d2715..d23f791932f0 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -448,28 +448,7 @@ js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, inline JSObject * CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, - bool ignoreSingletonClone = false) -{ - JS_ASSERT(parent); - JSObject *proto; - if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto)) - return NULL; - - /* - * For attempts to clone functions at a function definition opcode or from - * a method barrier, don't perform the clone if the function has singleton - * type. CloneFunctionObject was called pessimistically, and we need to - * preserve the type's property that if it is singleton there is only a - * single object with its type in existence. - */ - if (ignoreSingletonClone && fun->hasSingletonType()) { - JS_ASSERT(fun->getProto() == proto); - fun->setParent(parent); - return fun; - } - - return js_CloneFunctionObject(cx, fun, parent, proto); -} + bool ignoreSingletonClone = false); inline JSObject * CloneFunctionObject(JSContext *cx, JSFunction *fun) diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 248315eaa37e..777f195fee5f 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -43,6 +43,8 @@ #include "jsfun.h" #include "jsscript.h" +#include "vm/GlobalObject.h" + inline bool js::IsConstructing(CallReceiver call) { @@ -70,4 +72,29 @@ JSFunction::setMethodAtom(JSAtom *atom) setSlot(METHOD_ATOM_SLOT, js::StringValue(atom)); } +inline JSObject * +CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, + bool ignoreSingletonClone /* = false */) +{ + JS_ASSERT(parent); + JSObject *proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx); + if (!proto) + return NULL; + + /* + * For attempts to clone functions at a function definition opcode or from + * a method barrier, don't perform the clone if the function has singleton + * type. CloneFunctionObject was called pessimistically, and we need to + * preserve the type's property that if it is singleton there is only a + * single object with its type in existence. + */ + if (ignoreSingletonClone && fun->hasSingletonType()) { + JS_ASSERT(fun->getProto() == proto); + fun->setParent(parent); + return fun; + } + + return js_CloneFunctionObject(cx, fun, parent, proto); +} + #endif /* jsfuninlines_h___ */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 692a78af0942..dabc44311080 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -838,7 +838,7 @@ js::CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs) if (obj2->isNative()) { oldAttrs = ((Shape *) prop)->attributes(); } else { - if (!obj2->getAttributes(cx, id, &oldAttrs)) + if (!obj2->getGenericAttributes(cx, id, &oldAttrs)) return false; } @@ -2661,7 +2661,7 @@ BEGIN_CASE(JSOP_SETCONST) LOAD_ATOM(0, atom); JSObject &obj = regs.fp()->varObj(); const Value &ref = regs.sp[-1]; - if (!obj.defineProperty(cx, ATOM_TO_JSID(atom), ref, + if (!obj.defineProperty(cx, atom->asPropertyName(), ref, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) { goto error; @@ -2677,9 +2677,9 @@ BEGIN_CASE(JSOP_ENUMCONSTELEM) FETCH_OBJECT(cx, -2, obj); jsid id; FETCH_ELEMENT_ID(obj, -1, id); - if (!obj->defineProperty(cx, id, ref, - JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) { + if (!obj->defineGeneric(cx, id, ref, + JS_PropertyStub, JS_StrictPropertyStub, + JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) { goto error; } regs.sp -= 3; @@ -3137,7 +3137,7 @@ BEGIN_CASE(JSOP_DELNAME) /* ECMA says to return true if name is undefined or inherited. */ PUSH_BOOLEAN(true); if (prop) { - if (!obj->deleteProperty(cx, id, ®s.sp[-1], false)) + if (!obj->deleteProperty(cx, atom->asPropertyName(), ®s.sp[-1], false)) goto error; } } @@ -3153,7 +3153,7 @@ BEGIN_CASE(JSOP_DELPROP) FETCH_OBJECT(cx, -1, obj); Value rval; - if (!obj->deleteProperty(cx, id, &rval, script->strictModeCode)) + if (!obj->deleteGeneric(cx, id, &rval, script->strictModeCode)) goto error; regs.sp[-1] = rval; @@ -3171,7 +3171,7 @@ BEGIN_CASE(JSOP_DELELEM) FETCH_ELEMENT_ID(obj, -1, id); /* Get or set the element. */ - if (!obj->deleteProperty(cx, id, ®s.sp[-2], script->strictModeCode)) + if (!obj->deleteGeneric(cx, id, ®s.sp[-2], script->strictModeCode)) goto error; regs.sp--; @@ -3342,7 +3342,7 @@ do_incop: { JSAutoResolveFlags rf(cx, setPropFlags); - if (!obj->setProperty(cx, id, &ref, script->strictModeCode)) + if (!obj->setGeneric(cx, id, &ref, script->strictModeCode)) goto error; } @@ -3359,7 +3359,7 @@ do_incop: { JSAutoResolveFlags rf(cx, setPropFlags); - if (!obj->setProperty(cx, id, ®s.sp[-1], script->strictModeCode)) + if (!obj->setGeneric(cx, id, ®s.sp[-1], script->strictModeCode)) goto error; } @@ -3557,20 +3557,20 @@ BEGIN_CASE(JSOP_CALLPROP) if (lval.isObject()) { objv = lval; } else { - JSProtoKey protoKey; + GlobalObject *global = regs.fp()->scopeChain().getGlobal(); + JSObject *pobj; if (lval.isString()) { - protoKey = JSProto_String; + pobj = global->getOrCreateStringPrototype(cx); } else if (lval.isNumber()) { - protoKey = JSProto_Number; + pobj = global->getOrCreateNumberPrototype(cx); } else if (lval.isBoolean()) { - protoKey = JSProto_Boolean; + pobj = global->getOrCreateBooleanPrototype(cx); } else { JS_ASSERT(lval.isNull() || lval.isUndefined()); js_ReportIsNullOrUndefined(cx, -1, lval, NULL); goto error; } - JSObject *pobj; - if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj)) + if (!pobj) goto error; objv.setObject(*pobj); } @@ -3795,7 +3795,7 @@ BEGIN_CASE(JSOP_SETMETHOD) if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)) goto error; } else { - if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) + if (!obj->setGeneric(cx, id, &rval, script->strictModeCode)) goto error; ABORT_RECORDING(cx, "Non-native set"); } @@ -3944,7 +3944,7 @@ BEGIN_CASE(JSOP_SETELEM) } } while (0); rval = regs.sp[-1]; - if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) + if (!obj->setGeneric(cx, id, &rval, script->strictModeCode)) goto error; end_setelem:; } @@ -3958,7 +3958,7 @@ BEGIN_CASE(JSOP_ENUMELEM) jsid id; FETCH_ELEMENT_ID(obj, -1, id); Value rval = regs.sp[-3]; - if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) + if (!obj->setGeneric(cx, id, &rval, script->strictModeCode)) goto error; regs.sp -= 3; } @@ -4215,17 +4215,12 @@ BEGIN_CASE(JSOP_REGEXP) { /* * Push a regexp object cloned from the regexp literal object mapped by the - * bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was - * flouted by many browser-based implementations. - * - * We avoid the GetScopeChain call here and pass fp->scopeChain as - * js_GetClassPrototype uses the latter only to locate the global. + * bytecode at pc. */ jsatomid index = GET_FULL_INDEX(0); - JSObject *proto; - if (!js_GetClassPrototype(cx, ®s.fp()->scopeChain(), JSProto_RegExp, &proto)) + JSObject *proto = regs.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(cx); + if (!proto) goto error; - JS_ASSERT(proto); JSObject *obj = js_CloneRegExpObject(cx, script->getRegExp(index), proto); if (!obj) goto error; @@ -4668,8 +4663,11 @@ BEGIN_CASE(JSOP_DEFFUN) do { /* Steps 5d, 5f. */ if (!prop || pobj != parent) { - if (!parent->defineProperty(cx, id, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) + if (!parent->defineProperty(cx, name, rval, + JS_PropertyStub, JS_StrictPropertyStub, attrs)) + { goto error; + } break; } @@ -4678,8 +4676,11 @@ BEGIN_CASE(JSOP_DEFFUN) Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { - if (!parent->defineProperty(cx, id, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) + if (!parent->defineProperty(cx, name, rval, + JS_PropertyStub, JS_StrictPropertyStub, attrs)) + { goto error; + } break; } @@ -4701,7 +4702,7 @@ BEGIN_CASE(JSOP_DEFFUN) */ /* Step 5f. */ - if (!parent->setProperty(cx, id, &rval, script->strictModeCode)) + if (!parent->setProperty(cx, name, &rval, script->strictModeCode)) goto error; } while (false); } @@ -4728,9 +4729,11 @@ BEGIN_CASE(JSOP_DEFFUN_FC) if (!CheckRedeclaration(cx, &parent, id, attrs)) goto error; + PropertyName *name = fun->atom->asPropertyName(); if ((attrs == JSPROP_ENUMERATE) - ? !parent.setProperty(cx, id, &rval, script->strictModeCode) - : !parent.defineProperty(cx, id, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) { + ? !parent.setProperty(cx, name, &rval, script->strictModeCode) + : !parent.defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) + { goto error; } } @@ -5020,7 +5023,7 @@ BEGIN_CASE(JSOP_SETTER) if (!CheckRedeclaration(cx, obj, id, attrs)) goto error; - if (!obj->defineProperty(cx, id, UndefinedValue(), getter, setter, attrs)) + if (!obj->defineGeneric(cx, id, UndefinedValue(), getter, setter, attrs)) goto error; regs.sp += i; @@ -5209,7 +5212,7 @@ BEGIN_CASE(JSOP_INITELEM) goto error; } } else { - if (!obj->defineProperty(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) + if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) goto error; } regs.sp -= 2; @@ -5243,7 +5246,7 @@ BEGIN_CASE(JSOP_DEFSHARP) JSMSG_BAD_SHARP_DEF, numBuf); goto error; } - if (!obj->defineProperty(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) + if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) goto error; } END_CASE(JSOP_DEFSHARP) @@ -5570,7 +5573,7 @@ BEGIN_CASE(JSOP_SETXMLNAME) Value rval = regs.sp[-1]; jsid id; FETCH_ELEMENT_ID(obj, -2, id); - if (!obj->setProperty(cx, id, &rval, script->strictModeCode)) + if (!obj->setGeneric(cx, id, &rval, script->strictModeCode)) goto error; rval = regs.sp[-1]; regs.sp -= 2; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 1233af22df7d..9f870259f002 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -871,7 +871,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat uintN attrs; if (obj2.object()->isNative()) attrs = ((Shape *) prop)->attributes(); - else if (!obj2.object()->getAttributes(cx, *idp, &attrs)) + else if (!obj2.object()->getGenericAttributes(cx, *idp, &attrs)) return false; if (attrs & JSPROP_ENUMERATE) diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index fc9a9ebcf074..afa2125fa759 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -640,7 +640,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) * If id is a string that's not an identifier, or if it's a negative * integer, then it must be quoted. */ - bool idIsLexicalIdentifier = js_IsIdentifier(idstr); + bool idIsLexicalIdentifier = IsIdentifier(idstr); if (JSID_IS_ATOM(id) ? !idIsLexicalIdentifier : (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0)) { @@ -1027,14 +1027,14 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, uintN st script->principals->subsume(script->principals, principals)))) { /* * Get the prior (cache-filling) eval's saved caller function. - * See Compiler::compileScript in jsparse.cpp. + * See BytecodeCompiler::compileScript. */ JSFunction *fun = script->getCallerFunction(); if (fun == caller->fun()) { /* - * Get the source string passed for safekeeping in the - * atom map by the prior eval to Compiler::compileScript. + * Get the source string passed for safekeeping in the atom map + * by the prior eval to BytecodeCompiler::compileScript. */ JSAtom *src = script->atoms[0]; @@ -1273,9 +1273,10 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *c ? CALLED_FROM_JSOP_EVAL : NOT_CALLED_FROM_JSOP_EVAL); uint32 tcflags = TCF_COMPILE_N_GO | TCF_NEED_MUTABLE_SCRIPT | TCF_COMPILE_FOR_EVAL; - JSScript *compiled = Compiler::compileScript(cx, &scopeobj, caller, principals, tcflags, - chars, length, filename, lineno, - cx->findVersion(), linearStr, staticLevel); + JSScript *compiled = BytecodeCompiler::compileScript(cx, &scopeobj, caller, principals, + tcflags, chars, length, filename, + lineno, cx->findVersion(), linearStr, + staticLevel); if (!compiled) return false; @@ -1595,7 +1596,7 @@ js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, Value *vp) } uintN attrs; - if (!pobj->getAttributes(cx, id, &attrs)) + if (!pobj->getGenericAttributes(cx, id, &attrs)) return false; vp->setBoolean((attrs & JSPROP_ENUMERATE) != 0); @@ -1639,8 +1640,8 @@ js::obj_defineGetter(JSContext *cx, uintN argc, Value *vp) if (!CheckAccess(cx, obj, id, JSACC_WATCH, &junk, &attrs)) return JS_FALSE; args.rval().setUndefined(); - return obj->defineProperty(cx, id, UndefinedValue(), getter, JS_StrictPropertyStub, - JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED); + return obj->defineGeneric(cx, id, UndefinedValue(), getter, JS_StrictPropertyStub, + JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED); } JS_FRIEND_API(JSBool) @@ -1673,8 +1674,8 @@ js::obj_defineSetter(JSContext *cx, uintN argc, Value *vp) if (!CheckAccess(cx, obj, id, JSACC_WATCH, &junk, &attrs)) return JS_FALSE; args.rval().setUndefined(); - return obj->defineProperty(cx, id, UndefinedValue(), JS_PropertyStub, setter, - JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED); + return obj->defineGeneric(cx, id, UndefinedValue(), JS_PropertyStub, setter, + JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED); } static JSBool @@ -1808,26 +1809,20 @@ PropDesc::makeObject(JSContext *cx) const JSAtomState &atomState = cx->runtime->atomState; if ((hasConfigurable && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.configurableAtom), - BooleanValue((attrs & JSPROP_PERMANENT) == 0), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) || + !obj->defineProperty(cx, atomState.configurableAtom, + BooleanValue((attrs & JSPROP_PERMANENT) == 0))) || (hasEnumerable && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.enumerableAtom), - BooleanValue((attrs & JSPROP_ENUMERATE) != 0), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) || + !obj->defineProperty(cx, atomState.enumerableAtom, + BooleanValue((attrs & JSPROP_ENUMERATE) != 0))) || (hasGet && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.getAtom), get, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) || + !obj->defineProperty(cx, atomState.getAtom, get)) || (hasSet && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.setAtom), set, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) || + !obj->defineProperty(cx, atomState.setAtom, set)) || (hasValue && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.valueAtom), value, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE)) || + !obj->defineProperty(cx, atomState.valueAtom, value)) || (hasWritable && - !obj->defineProperty(cx, ATOM_TO_JSID(atomState.writableAtom), - BooleanValue((attrs & JSPROP_READONLY) == 0), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE))) + !obj->defineProperty(cx, atomState.writableAtom, + BooleanValue((attrs & JSPROP_READONLY) == 0)))) { return false; } @@ -1863,7 +1858,7 @@ GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescript desc->setter = CastAsStrictPropertyOp(shape->setterObject()); } } else { - if (!pobj->getAttributes(cx, id, &desc->attrs)) + if (!pobj->getGenericAttributes(cx, id, &desc->attrs)) return false; } @@ -2750,7 +2745,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it) jsid id = props[i]; uintN attrs; - if (!getAttributes(cx, id, &attrs)) + if (!getGenericAttributes(cx, id, &attrs)) return false; /* Make all attributes permanent; if freezing, make data attributes read-only. */ @@ -2765,7 +2760,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it) continue; attrs |= new_attrs; - if (!setAttributes(cx, id, &attrs)) + if (!setGenericAttributes(cx, id, &attrs)) return false; } @@ -2788,7 +2783,7 @@ JSObject::isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp) jsid id = props[i]; uintN attrs; - if (!getAttributes(cx, id, &attrs)) + if (!getGenericAttributes(cx, id, &attrs)) return false; /* @@ -3132,7 +3127,8 @@ js_CreateThisFromTrace(JSContext *cx, JSObject *ctor, uintN protoSlot) * GetInterpretedFunctionPrototype found that ctor.prototype is * primitive. Use Object.prototype for proto, per ES5 13.2.2 step 7. */ - if (!js_GetClassPrototype(cx, parent, JSProto_Object, &proto)) + proto = parent->getGlobal()->getOrCreateObjectPrototype(cx); + if (!proto) return NULL; } @@ -3316,87 +3312,99 @@ with_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, } static JSBool -with_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +with_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { - return obj->getProto()->setProperty(cx, id, vp, strict); + return obj->getProto()->setGeneric(cx, id, vp, strict); +} + +static JSBool +with_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) +{ + return obj->getProto()->setProperty(cx, name, vp, strict); } static JSBool with_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict) { - jsid id; - if (!IndexToId(cx, index, &id)) - return false; - return with_SetProperty(cx, obj, id, vp, strict); + return obj->getProto()->setElement(cx, index, vp, strict); } static JSBool with_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict) { - return with_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); + return obj->getProto()->setSpecial(cx, sid, vp, strict); } static JSBool -with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +with_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { - return obj->getProto()->getAttributes(cx, id, attrsp); + return obj->getProto()->getGenericAttributes(cx, id, attrsp); +} + +static JSBool +with_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return obj->getProto()->getPropertyAttributes(cx, name, attrsp); } static JSBool with_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { - jsid id; - if (!IndexToId(cx, index, &id)) - return false; - return with_GetAttributes(cx, obj, id, attrsp); + return obj->getProto()->getElementAttributes(cx, index, attrsp); } static JSBool with_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return with_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return obj->getProto()->getSpecialAttributes(cx, sid, attrsp); } static JSBool -with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +with_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { - return obj->getProto()->setAttributes(cx, id, attrsp); + return obj->getProto()->setGenericAttributes(cx, id, attrsp); +} + +static JSBool +with_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return obj->getProto()->setPropertyAttributes(cx, name, attrsp); } static JSBool with_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { - jsid id; - if (!IndexToId(cx, index, &id)) - return false; - return with_SetAttributes(cx, obj, id, attrsp); + return obj->getProto()->setElementAttributes(cx, index, attrsp); } static JSBool with_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return with_SetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return obj->getProto()->setSpecialAttributes(cx, sid, attrsp); } static JSBool -with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) +with_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { - return obj->getProto()->deleteProperty(cx, id, rval, strict); + return obj->getProto()->deleteGeneric(cx, id, rval, strict); +} + +static JSBool +with_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) +{ + return obj->getProto()->deleteProperty(cx, name, rval, strict); } static JSBool with_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) { - jsid id; - if (!IndexToId(cx, index, &id)) - return false; - return with_DeleteProperty(cx, obj, id, rval, strict); + return obj->getProto()->deleteElement(cx, index, rval, strict); } static JSBool with_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return with_DeleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return obj->getProto()->deleteSpecial(cx, sid, rval, strict); } static JSBool @@ -3450,19 +3458,19 @@ Class js::WithClass = { with_GetProperty, with_GetElement, with_GetSpecial, - with_SetProperty, + with_SetGeneric, with_SetProperty, with_SetElement, with_SetSpecial, - with_GetAttributes, - with_GetAttributes, + with_GetGenericAttributes, + with_GetPropertyAttributes, with_GetElementAttributes, with_GetSpecialAttributes, - with_SetAttributes, - with_SetAttributes, + with_SetGenericAttributes, + with_SetPropertyAttributes, with_SetElementAttributes, with_SetSpecialAttributes, - with_DeleteProperty, + with_DeleteGeneric, with_DeleteProperty, with_DeleteElement, with_DeleteSpecial, @@ -3576,7 +3584,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind) JS_ASSERT(depth <= size_t(cx->regs().sp - fp->base())); JS_ASSERT(count <= size_t(cx->regs().sp - fp->base() - depth)); - /* See comments in CheckDestructuring from jsparse.cpp. */ + /* See comments in CheckDestructuring in frontend/Parser.cpp. */ JS_ASSERT(count >= 1); if (normalUnwind) { @@ -3667,7 +3675,7 @@ JSObject::nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool str if (wpmap && !wpmap->triggerWatchpoint(cx, this, id, vp)) return false; } - return getOps()->setProperty(cx, this, id, vp, strict); + return getOps()->setGeneric(cx, this, id, vp, strict); } JSBool @@ -3712,7 +3720,7 @@ JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj) Value v = shape->hasSlot() ? obj->getSlot(shape->slot) : UndefinedValue(); if (!cx->compartment->wrap(cx, &v)) return false; - if (!target->defineProperty(cx, shape->propid, v, getter, setter, attrs)) + if (!target->defineGeneric(cx, shape->propid, v, getter, setter, attrs)) return false; } return true; @@ -4181,7 +4189,7 @@ DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom, } } - named = obj->defineProperty(cx, id, v, JS_PropertyStub, JS_StrictPropertyStub, attrs); + named = obj->defineGeneric(cx, id, v, JS_PropertyStub, JS_StrictPropertyStub, attrs); return named; } @@ -4360,7 +4368,7 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt bad: if (named) { Value rval; - obj->deleteProperty(cx, ATOM_TO_JSID(atom), &rval, false); + obj->deleteGeneric(cx, ATOM_TO_JSID(atom), &rval, false); } if (cached) ClearClassObject(cx, obj, key); @@ -6336,7 +6344,7 @@ js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return true; } if (!obj->isNative()) - return obj->getAttributes(cx, id, attrsp); + return obj->getGenericAttributes(cx, id, attrsp); const Shape *shape = (Shape *)prop; *attrsp = shape->attributes(); @@ -6379,7 +6387,7 @@ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return true; return obj->isNative() ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp) - : obj->setAttributes(cx, id, attrsp); + : obj->setGenericAttributes(cx, id, attrsp); } JSBool diff --git a/js/src/jsobj.h b/js/src/jsobj.h index d673d3f4ae7a..e708724315f6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1357,22 +1357,22 @@ struct JSObject : js::gc::Cell { inline JSBool lookupElement(JSContext *cx, uint32 index, JSObject **objp, JSProperty **propp); inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid, JSObject **objp, JSProperty **propp); - JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value, - JSPropertyOp getter = JS_PropertyStub, - JSStrictPropertyOp setter = JS_StrictPropertyStub, - uintN attrs = JSPROP_ENUMERATE) { - js::DefinePropOp op = getOps()->defineProperty; - return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); - } - - JSBool defineElement(JSContext *cx, uint32 index, const js::Value &value, - JSPropertyOp getter = JS_PropertyStub, - JSStrictPropertyOp setter = JS_StrictPropertyStub, - uintN attrs = JSPROP_ENUMERATE) - { - js::DefineElementOp op = getOps()->defineElement; - return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs); - } + inline JSBool defineGeneric(JSContext *cx, jsid id, const js::Value &value, + JSPropertyOp getter = JS_PropertyStub, + JSStrictPropertyOp setter = JS_StrictPropertyStub, + uintN attrs = JSPROP_ENUMERATE); + inline JSBool defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value, + JSPropertyOp getter = JS_PropertyStub, + JSStrictPropertyOp setter = JS_StrictPropertyStub, + uintN attrs = JSPROP_ENUMERATE); + inline JSBool defineElement(JSContext *cx, uint32 index, const js::Value &value, + JSPropertyOp getter = JS_PropertyStub, + JSStrictPropertyOp setter = JS_StrictPropertyStub, + uintN attrs = JSPROP_ENUMERATE); + inline JSBool defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value, + JSPropertyOp getter = JS_PropertyStub, + JSStrictPropertyOp setter = JS_StrictPropertyStub, + uintN attrs = JSPROP_ENUMERATE); inline JSBool getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp); inline JSBool getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name, @@ -1385,42 +1385,29 @@ struct JSObject : js::gc::Cell { inline JSBool getElement(JSContext *cx, uint32 index, js::Value *vp); inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp); - JSBool setProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict) { - if (getOps()->setProperty) - return nonNativeSetProperty(cx, id, vp, strict); - return js_SetPropertyHelper(cx, this, id, 0, vp, strict); - } - - JSBool setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict) { - if (getOps()->setElement) - return nonNativeSetElement(cx, index, vp, strict); - return js_SetElementHelper(cx, this, index, 0, vp, strict); - } + inline JSBool setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict); + inline JSBool setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict); + inline JSBool setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict); + inline JSBool setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict); JSBool nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict); JSBool nonNativeSetElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict); - JSBool getAttributes(JSContext *cx, jsid id, uintN *attrsp) { - js::AttributesOp op = getOps()->getAttributes; - return (op ? op : js_GetAttributes)(cx, this, id, attrsp); - } + inline JSBool getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp); + inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp); + inline JSBool getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp); + inline JSBool getSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp); - JSBool getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) { - js::ElementAttributesOp op = getOps()->getElementAttributes; - return (op ? op : js_GetElementAttributes)(cx, this, index, attrsp); - } - - inline JSBool setAttributes(JSContext *cx, jsid id, uintN *attrsp); - - JSBool setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) { - js::ElementAttributesOp op = getOps()->setElementAttributes; - return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp); - } - - inline JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict); + inline JSBool setGenericAttributes(JSContext *cx, jsid id, uintN *attrsp); + inline JSBool setPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp); + inline JSBool setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp); + inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp); + inline JSBool deleteGeneric(JSContext *cx, jsid id, js::Value *rval, JSBool strict); + inline JSBool deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, JSBool strict); inline JSBool deleteElement(JSContext *cx, uint32 index, js::Value *rval, JSBool strict); + inline JSBool deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, JSBool strict); JSBool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp) { JSNewEnumerateOp op = getOps()->enumerate; diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index e290ddaf2a06..94d624bf121b 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -126,13 +126,60 @@ JSObject::unbrand(JSContext *cx) } inline JSBool -JSObject::setAttributes(JSContext *cx, jsid id, uintN *attrsp) +JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict) +{ + if (getOps()->setGeneric) + return nonNativeSetProperty(cx, id, vp, strict); + return js_SetPropertyHelper(cx, this, id, 0, vp, strict); +} + +inline JSBool +JSObject::setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict) +{ + return setGeneric(cx, ATOM_TO_JSID(name), vp, strict); +} + +inline JSBool +JSObject::setElement(JSContext *cx, uint32 index, js::Value *vp, JSBool strict) +{ + if (getOps()->setElement) + return nonNativeSetElement(cx, index, vp, strict); + return js_SetElementHelper(cx, this, index, 0, vp, strict); +} + +inline JSBool +JSObject::setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict) +{ + return setGeneric(cx, SPECIALID_TO_JSID(sid), vp, strict); +} + +inline JSBool +JSObject::setGenericAttributes(JSContext *cx, jsid id, uintN *attrsp) { js::types::MarkTypePropertyConfigured(cx, this, id); - js::AttributesOp op = getOps()->setAttributes; + js::GenericAttributesOp op = getOps()->setGenericAttributes; return (op ? op : js_SetAttributes)(cx, this, id, attrsp); } +inline JSBool +JSObject::setPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp) +{ + return setGenericAttributes(cx, ATOM_TO_JSID(name), attrsp); +} + +inline JSBool +JSObject::setElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) +{ + js::ElementAttributesOp op = getOps()->setElementAttributes; + return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp); +} + +inline JSBool +JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp) +{ + return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp); +} + inline JSBool JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp) { @@ -166,15 +213,36 @@ JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp) } inline JSBool -JSObject::deleteProperty(JSContext *cx, jsid id, js::Value *rval, JSBool strict) +JSObject::deleteGeneric(JSContext *cx, jsid id, js::Value *rval, JSBool strict) { js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType()); js::types::MarkTypePropertyConfigured(cx, this, id); - js::DeleteIdOp op = getOps()->deleteProperty; + js::DeleteGenericOp op = getOps()->deleteGeneric; return (op ? op : js_DeleteProperty)(cx, this, id, rval, strict); } +inline JSBool +JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, JSBool strict) +{ + return deleteGeneric(cx, ATOM_TO_JSID(name), rval, strict); +} + +inline JSBool +JSObject::deleteElement(JSContext *cx, uint32 index, js::Value *rval, JSBool strict) +{ + jsid id; + if (!js::IndexToId(cx, index, &id)) + return false; + return deleteGeneric(cx, id, rval, strict); +} + +inline JSBool +JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, JSBool strict) +{ + return deleteGeneric(cx, SPECIALID_TO_JSID(sid), rval, strict); +} + inline void JSObject::syncSpecialEquality() { @@ -1116,6 +1184,44 @@ JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, return lookupGeneric(cx, ATOM_TO_JSID(name), objp, propp); } +inline JSBool +JSObject::defineGeneric(JSContext *cx, jsid id, const js::Value &value, + JSPropertyOp getter /* = JS_PropertyStub */, + JSStrictPropertyOp setter /* = JS_StrictPropertyStub */, + uintN attrs /* = JSPROP_ENUMERATE */) +{ + js::DefineGenericOp op = getOps()->defineGeneric; + return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs); +} + +inline JSBool +JSObject::defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value, + JSPropertyOp getter /* = JS_PropertyStub */, + JSStrictPropertyOp setter /* = JS_StrictPropertyStub */, + uintN attrs /* = JSPROP_ENUMERATE */) +{ + return defineGeneric(cx, ATOM_TO_JSID(name), value, getter, setter, attrs); +} + +inline JSBool +JSObject::defineElement(JSContext *cx, uint32 index, const js::Value &value, + JSPropertyOp getter /* = JS_PropertyStub */, + JSStrictPropertyOp setter /* = JS_StrictPropertyStub */, + uintN attrs /* = JSPROP_ENUMERATE */) +{ + js::DefineElementOp op = getOps()->defineElement; + return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs); +} + +inline JSBool +JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value, + JSPropertyOp getter /* = JS_PropertyStub */, + JSStrictPropertyOp setter /* = JS_StrictPropertyStub */, + uintN attrs /* = JSPROP_ENUMERATE */) +{ + return defineGeneric(cx, SPECIALID_TO_JSID(sid), value, getter, setter, attrs); +} + inline JSBool JSObject::lookupElement(JSContext *cx, uint32 index, JSObject **objp, JSProperty **propp) { @@ -1148,18 +1254,37 @@ JSObject::getElement(JSContext *cx, uint32 index, js::Value *vp) } inline JSBool -JSObject::deleteElement(JSContext *cx, uint32 index, js::Value *rval, JSBool strict) +JSObject::getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp) +{ + return getGeneric(cx, SPECIALID_TO_JSID(sid), vp); +} + +inline JSBool +JSObject::getGenericAttributes(JSContext *cx, jsid id, uintN *attrsp) +{ + js::GenericAttributesOp op = getOps()->getGenericAttributes; + return (op ? op : js_GetAttributes)(cx, this, id, attrsp); +} + +inline JSBool +JSObject::getPropertyAttributes(JSContext *cx, js::PropertyName *name, uintN *attrsp) +{ + return getGenericAttributes(cx, ATOM_TO_JSID(name), attrsp); +} + +inline JSBool +JSObject::getElementAttributes(JSContext *cx, uint32 index, uintN *attrsp) { jsid id; if (!js::IndexToId(cx, index, &id)) return false; - return deleteProperty(cx, id, rval, strict); + return getGenericAttributes(cx, id, attrsp); } inline JSBool -JSObject::getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp) +JSObject::getSpecialAttributes(JSContext *cx, js::SpecialId sid, uintN *attrsp) { - return getGeneric(cx, SPECIALID_TO_JSID(sid), vp); + return getGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp); } inline bool diff --git a/js/src/json.cpp b/js/src/json.cpp index b0ef520c1548..c18712858c77 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -62,6 +62,7 @@ #include "frontend/TokenStream.h" #include "jsatominlines.h" +#include "jsboolinlines.h" #include "jsinferinlines.h" #include "jsobjinlines.h" #include "jsstrinlines.h" @@ -791,10 +792,10 @@ Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp JS_ASSERT(!obj->isProxy()); if (obj->isArray()) { /* Step 2a(ii). */ - jsuint length = obj->getArrayLength(); + uint32 length = obj->getArrayLength(); /* Step 2a(i), 2a(iii-iv). */ - for (jsuint i = 0; i < length; i++) { + for (uint32 i = 0; i < length; i++) { jsid id; if (!IndexToId(cx, i, &id)) return false; @@ -817,11 +818,11 @@ Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp */ if (newElement.isUndefined()) { /* Step 2a(iii)(2). */ - JS_ALWAYS_TRUE(array_deleteProperty(cx, obj, id, &newElement, false)); + JS_ALWAYS_TRUE(array_deleteElement(cx, obj, i, &newElement, false)); } else { /* Step 2a(iii)(3). */ - JS_ALWAYS_TRUE(array_defineProperty(cx, obj, id, &newElement, JS_PropertyStub, - JS_StrictPropertyStub, JSPROP_ENUMERATE)); + JS_ALWAYS_TRUE(array_defineElement(cx, obj, i, &newElement, JS_PropertyStub, + JS_StrictPropertyStub, JSPROP_ENUMERATE)); } } } else { @@ -884,11 +885,8 @@ Revive(JSContext *cx, const Value &reviver, Value *vp) if (!obj) return false; - AutoObjectRooter tvr(cx, obj); - if (!obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.emptyAtom), - *vp, NULL, NULL, JSPROP_ENUMERATE)) { + if (!obj->defineProperty(cx, cx->runtime->atomState.emptyAtom, *vp)) return false; - } return Walk(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.emptyAtom), reviver, vp); } diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index b705f8c408d5..73e781bfb9f0 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1753,10 +1753,8 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc) #if JS_HAS_DESTRUCTURING_SHORTHAND nameoff = ss->sprinter.offset; #endif - if (!QuoteString(&ss->sprinter, atom, - js_IsIdentifier(atom) ? 0 : (jschar)'\'')) { + if (!QuoteString(&ss->sprinter, atom, IsIdentifier(atom) ? 0 : (jschar)'\'')) return NULL; - } if (SprintPut(&ss->sprinter, ": ", 2) < 0) return NULL; break; @@ -1998,8 +1996,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) ? JSOP_IFEQ \ : JSOP_NOP) -#define ATOM_IS_IDENTIFIER(atom) js_IsIdentifier(atom) - /* * Given an atom already fetched from jp->script's atom map, quote/escape its * string appropriately into rval, and select fmt from the quoted and unquoted @@ -2008,7 +2004,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) #define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \ JS_BEGIN_MACRO \ jschar quote_; \ - if (!ATOM_IS_IDENTIFIER(atom)) { \ + if (!IsIdentifier(atom)) { \ quote_ = '\''; \ fmt = qfmt; \ } else { \ @@ -4563,8 +4559,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) case JSOP_INITPROP: case JSOP_INITMETHOD: LOAD_ATOM(0); - xval = QuoteString(&ss->sprinter, atom, - jschar(ATOM_IS_IDENTIFIER(atom) ? 0 : '\'')); + xval = QuoteString(&ss->sprinter, atom, jschar(IsIdentifier(atom) ? 0 : '\'')); if (!xval) return NULL; isFirst = IsInitializerOp(ss->opcodes[ss->top - 2]); @@ -4812,7 +4807,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) #undef POP_STR #undef POP_STR_PREC #undef LOCAL_ASSERT -#undef ATOM_IS_IDENTIFIER #undef GET_QUOTE_AND_FMT #undef GET_ATOM_QUOTE_AND_FMT diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index fe648a5f86ac..8b365de5d820 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -134,7 +134,7 @@ typedef enum JSOp { #define JOF_SHARPSLOT (1U<<24) /* first immediate is uint16 stack slot no. that needs fixup when in global code (see - Compiler::compileScript) */ + BytecodeCompiler::compileScript) */ #define JOF_GNAME (1U<<25) /* predicted global name */ #define JOF_TYPESET (1U<<26) /* has an entry in a script's type sets */ #define JOF_DECOMPOSE (1U<<27) /* followed by an equivalent decomposed @@ -177,7 +177,8 @@ typedef enum JSOp { * When a short jump won't hold a relative offset, its 2-byte immediate offset * operand is an unsigned index of a span-dependency record, maintained until * code generation finishes -- after which some (but we hope not nearly all) - * span-dependent jumps must be extended (see OptimizeSpanDeps in jsemit.c). + * span-dependent jumps must be extended (see js::frontend::OptimizeSpanDeps in + * frontend/BytecodeGenerator.cpp). * * If the span-dependency record index overflows SPANDEP_INDEX_MAX, the jump * offset will contain SPANDEP_INDEX_HUGE, indicating that the record must be diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index a2bea420ec6d..bba8d71f48f1 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -955,8 +955,8 @@ proxy_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp } static JSBool -proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, - PropertyOp getter, StrictPropertyOp setter, uintN attrs) +proxy_DefineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *value, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) { id = js_CheckForStringIndex(id); @@ -970,6 +970,13 @@ proxy_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value, return Proxy::defineProperty(cx, obj, id, &desc); } +static JSBool +proxy_DefineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) +{ + return proxy_DefineGeneric(cx, obj, ATOM_TO_JSID(name), value, getter, setter, attrs); +} + static JSBool proxy_DefineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *value, PropertyOp getter, StrictPropertyOp setter, uintN attrs) @@ -977,14 +984,14 @@ proxy_DefineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *val jsid id; if (!IndexToId(cx, index, &id)) return false; - return proxy_DefineProperty(cx, obj, id, value, getter, setter, attrs); + return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs); } static JSBool proxy_DefineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value, PropertyOp getter, StrictPropertyOp setter, uintN attrs) { - return proxy_DefineProperty(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs); + return proxy_DefineGeneric(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs); } static JSBool @@ -1017,30 +1024,36 @@ proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid } static JSBool -proxy_SetProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +proxy_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { id = js_CheckForStringIndex(id); return Proxy::set(cx, obj, obj, id, strict, vp); } +static JSBool +proxy_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) +{ + return proxy_SetGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict); +} + static JSBool proxy_SetElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return proxy_SetProperty(cx, obj, id, vp, strict); + return proxy_SetGeneric(cx, obj, id, vp, strict); } static JSBool proxy_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict) { - return proxy_SetProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); + return proxy_SetGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); } static JSBool -proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +proxy_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { id = js_CheckForStringIndex(id); @@ -1051,23 +1064,29 @@ proxy_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return true; } +static JSBool +proxy_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return proxy_GetGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + static JSBool proxy_GetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return proxy_GetAttributes(cx, obj, id, attrsp); + return proxy_GetGenericAttributes(cx, obj, id, attrsp); } static JSBool proxy_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return proxy_GetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return proxy_GetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } static JSBool -proxy_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +proxy_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { id = js_CheckForStringIndex(id); @@ -1079,23 +1098,29 @@ proxy_SetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return Proxy::defineProperty(cx, obj, id, &desc); } +static JSBool +proxy_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return proxy_SetGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + static JSBool proxy_SetElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return proxy_SetAttributes(cx, obj, id, attrsp); + return proxy_SetGenericAttributes(cx, obj, id, attrsp); } static JSBool proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return proxy_SetAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return proxy_SetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } static JSBool -proxy_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) +proxy_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { id = js_CheckForStringIndex(id); @@ -1107,19 +1132,25 @@ proxy_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool return true; } +static JSBool +proxy_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) +{ + return proxy_DeleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict); +} + static JSBool proxy_DeleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return proxy_DeleteProperty(cx, obj, id, rval, strict); + return proxy_DeleteGeneric(cx, obj, id, rval, strict); } static JSBool proxy_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return proxy_DeleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return proxy_DeleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); } static void @@ -1213,7 +1244,7 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = { proxy_LookupProperty, proxy_LookupElement, proxy_LookupSpecial, - proxy_DefineProperty, + proxy_DefineGeneric, proxy_DefineProperty, proxy_DefineElement, proxy_DefineSpecial, @@ -1221,19 +1252,19 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = { proxy_GetProperty, proxy_GetElement, proxy_GetSpecial, - proxy_SetProperty, + proxy_SetGeneric, proxy_SetProperty, proxy_SetElement, proxy_SetSpecial, - proxy_GetAttributes, - proxy_GetAttributes, + proxy_GetGenericAttributes, + proxy_GetPropertyAttributes, proxy_GetElementAttributes, proxy_GetSpecialAttributes, - proxy_SetAttributes, - proxy_SetAttributes, + proxy_SetGenericAttributes, + proxy_SetPropertyAttributes, proxy_SetElementAttributes, proxy_SetSpecialAttributes, - proxy_DeleteProperty, + proxy_DeleteGeneric, proxy_DeleteProperty, proxy_DeleteElement, proxy_DeleteSpecial, @@ -1274,7 +1305,7 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = { proxy_LookupProperty, proxy_LookupElement, proxy_LookupSpecial, - proxy_DefineProperty, + proxy_DefineGeneric, proxy_DefineProperty, proxy_DefineElement, proxy_DefineSpecial, @@ -1282,19 +1313,19 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = { proxy_GetProperty, proxy_GetElement, proxy_GetSpecial, - proxy_SetProperty, + proxy_SetGeneric, proxy_SetProperty, proxy_SetElement, proxy_SetSpecial, - proxy_GetAttributes, - proxy_GetAttributes, + proxy_GetGenericAttributes, + proxy_GetPropertyAttributes, proxy_GetElementAttributes, proxy_GetSpecialAttributes, - proxy_SetAttributes, - proxy_SetAttributes, + proxy_SetGenericAttributes, + proxy_SetPropertyAttributes, proxy_SetElementAttributes, proxy_SetSpecialAttributes, - proxy_DeleteProperty, + proxy_DeleteGeneric, proxy_DeleteProperty, proxy_DeleteElement, proxy_DeleteSpecial, @@ -1347,7 +1378,7 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = { proxy_LookupProperty, proxy_LookupElement, proxy_LookupSpecial, - proxy_DefineProperty, + proxy_DefineGeneric, proxy_DefineProperty, proxy_DefineElement, proxy_DefineSpecial, @@ -1355,19 +1386,19 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = { proxy_GetProperty, proxy_GetElement, proxy_GetSpecial, - proxy_SetProperty, + proxy_SetGeneric, proxy_SetProperty, proxy_SetElement, proxy_SetSpecial, - proxy_GetAttributes, - proxy_GetAttributes, + proxy_GetGenericAttributes, + proxy_GetPropertyAttributes, proxy_GetElementAttributes, proxy_GetSpecialAttributes, - proxy_SetAttributes, - proxy_SetAttributes, + proxy_SetGenericAttributes, + proxy_SetPropertyAttributes, proxy_SetElementAttributes, proxy_SetSpecialAttributes, - proxy_DeleteProperty, + proxy_DeleteGeneric, proxy_DeleteProperty, proxy_DeleteElement, proxy_DeleteSpecial, @@ -1461,7 +1492,8 @@ proxy_createFunction(JSContext *cx, uintN argc, Value *vp) return false; JSObject *proto, *parent; parent = vp[0].toObject().getParent(); - if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto)) + proto = parent->getGlobal()->getOrCreateFunctionPrototype(cx); + if (!proto) return false; parent = proto->getParent(); @@ -1574,7 +1606,8 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp) if (protov.isObject()) { proto = &protov.toObject(); } else { - if (!js_GetClassPrototype(cx, NULL, JSProto_Object, &proto)) + proto = callable->getGlobal()->getOrCreateObjectPrototype(cx); + if (!proto) return false; } diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index ac36749ccb38..b15fc9a19188 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -76,17 +76,12 @@ typedef uintptr_t jsatomid; /* Struct typedefs. */ typedef struct JSArgumentFormatMap JSArgumentFormatMap; -typedef struct JSCodeGenerator JSCodeGenerator; typedef struct JSGCThing JSGCThing; typedef struct JSGenerator JSGenerator; typedef struct JSNativeEnumerator JSNativeEnumerator; -typedef struct JSFunctionBox JSFunctionBox; -typedef struct JSObjectBox JSObjectBox; -typedef struct JSParseNode JSParseNode; typedef struct JSProperty JSProperty; typedef struct JSSharpObjectMap JSSharpObjectMap; typedef struct JSThread JSThread; -typedef struct JSTreeContext JSTreeContext; typedef struct JSTryNote JSTryNote; /* Friend "Advanced API" typedefs. */ @@ -120,7 +115,6 @@ class JSFixedString; class JSStaticAtom; class JSRope; class JSAtom; -struct JSDefinition; class JSWrapper; namespace js { @@ -164,12 +158,18 @@ class FrameRegsIter; class CallReceiver; class CallArgs; -struct Compiler; +struct BytecodeCompiler; +struct CodeGenerator; +struct Definition; +struct FunctionBox; +struct ObjectBox; +struct ParseNode; struct Parser; class TokenStream; struct Token; struct TokenPos; struct TokenPtr; +struct TreeContext; class UpvarCookie; class Proxy; @@ -218,7 +218,7 @@ class Bindings; class MultiDeclRange; class ParseMapPool; class DefnOrHeader; -typedef InlineMap AtomDefnMap; +typedef InlineMap AtomDefnMap; typedef InlineMap AtomIndexMap; typedef InlineMap AtomDOHMap; typedef Vector UpvarCookies; diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index 2d0a578f4c46..397a8ad9040c 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -137,7 +137,7 @@ char const *callbackNames[] = { typedef AutoValueVector NodeVector; /* - * JSParseNode is a somewhat intricate data structure, and its invariants have + * ParseNode is a somewhat intricate data structure, and its invariants have * evolved, making it more likely that there could be a disconnect between the * parser and the AST serializer. We use these macros to check invariants on a * parse node and raise a dynamic error on failure. @@ -428,7 +428,7 @@ class NodeBuilder if (!atom) return false; - return obj->defineProperty(cx, ATOM_TO_JSID(atom), val); + return obj->defineProperty(cx, atom->asPropertyName(), val); } bool newNodeLoc(TokenPos *pos, Value *dst); @@ -660,7 +660,7 @@ NodeBuilder::newArray(NodeVector &elts, Value *dst) if (val.isMagic(JS_SERIALIZE_NO_NODE)) continue; - if (!array->setProperty(cx, INT_TO_JSID(i), &val, false)) + if (!array->setElement(cx, i, &val, false)) return false; } @@ -1593,7 +1593,7 @@ NodeBuilder::xmlPI(Value target, Value contents, TokenPos *pos, Value *dst) /* * Serialization of parse nodes to JavaScript objects. * - * All serialization methods take a non-nullable JSParseNode pointer. + * All serialization methods take a non-nullable ParseNode pointer. */ class ASTSerializer @@ -1611,21 +1611,21 @@ class ASTSerializer UnaryOperator unop(TokenKind tk, JSOp op); AssignmentOperator aop(JSOp op); - bool statements(JSParseNode *pn, NodeVector &elts); - bool expressions(JSParseNode *pn, NodeVector &elts); - bool xmls(JSParseNode *pn, NodeVector &elts); - bool leftAssociate(JSParseNode *pn, Value *dst); - bool functionArgs(JSParseNode *pn, JSParseNode *pnargs, JSParseNode *pndestruct, - JSParseNode *pnbody, NodeVector &args); + bool statements(ParseNode *pn, NodeVector &elts); + bool expressions(ParseNode *pn, NodeVector &elts); + bool xmls(ParseNode *pn, NodeVector &elts); + bool leftAssociate(ParseNode *pn, Value *dst); + bool functionArgs(ParseNode *pn, ParseNode *pnargs, ParseNode *pndestruct, ParseNode *pnbody, + NodeVector &args); - bool sourceElement(JSParseNode *pn, Value *dst); + bool sourceElement(ParseNode *pn, Value *dst); - bool declaration(JSParseNode *pn, Value *dst); - bool variableDeclaration(JSParseNode *pn, bool let, Value *dst); - bool variableDeclarator(JSParseNode *pn, VarDeclKind *pkind, Value *dst); - bool letHead(JSParseNode *pn, NodeVector &dtors); + bool declaration(ParseNode *pn, Value *dst); + bool variableDeclaration(ParseNode *pn, bool let, Value *dst); + bool variableDeclarator(ParseNode *pn, VarDeclKind *pkind, Value *dst); + bool letHead(ParseNode *pn, NodeVector &dtors); - bool optStatement(JSParseNode *pn, Value *dst) { + bool optStatement(ParseNode *pn, Value *dst) { if (!pn) { dst->setMagic(JS_SERIALIZE_NO_NODE); return true; @@ -1633,15 +1633,15 @@ class ASTSerializer return statement(pn, dst); } - bool forInit(JSParseNode *pn, Value *dst); - bool statement(JSParseNode *pn, Value *dst); - bool blockStatement(JSParseNode *pn, Value *dst); - bool switchStatement(JSParseNode *pn, Value *dst); - bool switchCase(JSParseNode *pn, Value *dst); - bool tryStatement(JSParseNode *pn, Value *dst); - bool catchClause(JSParseNode *pn, Value *dst); + bool forInit(ParseNode *pn, Value *dst); + bool statement(ParseNode *pn, Value *dst); + bool blockStatement(ParseNode *pn, Value *dst); + bool switchStatement(ParseNode *pn, Value *dst); + bool switchCase(ParseNode *pn, Value *dst); + bool tryStatement(ParseNode *pn, Value *dst); + bool catchClause(ParseNode *pn, Value *dst); - bool optExpression(JSParseNode *pn, Value *dst) { + bool optExpression(ParseNode *pn, Value *dst) { if (!pn) { dst->setMagic(JS_SERIALIZE_NO_NODE); return true; @@ -1649,10 +1649,10 @@ class ASTSerializer return expression(pn, dst); } - bool expression(JSParseNode *pn, Value *dst); + bool expression(ParseNode *pn, Value *dst); - bool propertyName(JSParseNode *pn, Value *dst); - bool property(JSParseNode *pn, Value *dst); + bool propertyName(ParseNode *pn, Value *dst); + bool property(ParseNode *pn, Value *dst); bool optIdentifier(JSAtom *atom, TokenPos *pos, Value *dst) { if (!atom) { @@ -1663,22 +1663,22 @@ class ASTSerializer } bool identifier(JSAtom *atom, TokenPos *pos, Value *dst); - bool identifier(JSParseNode *pn, Value *dst); - bool literal(JSParseNode *pn, Value *dst); + bool identifier(ParseNode *pn, Value *dst); + bool literal(ParseNode *pn, Value *dst); - bool pattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst); - bool arrayPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst); - bool objectPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst); + bool pattern(ParseNode *pn, VarDeclKind *pkind, Value *dst); + bool arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst); + bool objectPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst); - bool function(JSParseNode *pn, ASTType type, Value *dst); - bool functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *body); - bool functionBody(JSParseNode *pn, TokenPos *pos, Value *dst); + bool function(ParseNode *pn, ASTType type, Value *dst); + bool functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body); + bool functionBody(ParseNode *pn, TokenPos *pos, Value *dst); - bool comprehensionBlock(JSParseNode *pn, Value *dst); - bool comprehension(JSParseNode *pn, Value *dst); - bool generatorExpression(JSParseNode *pn, Value *dst); + bool comprehensionBlock(ParseNode *pn, Value *dst); + bool comprehension(ParseNode *pn, Value *dst); + bool generatorExpression(ParseNode *pn, Value *dst); - bool xml(JSParseNode *pn, Value *dst); + bool xml(ParseNode *pn, Value *dst); public: ASTSerializer(JSContext *c, bool l, char const *src, uint32 ln) @@ -1693,7 +1693,7 @@ class ASTSerializer parser = p; } - bool program(JSParseNode *pn, Value *dst); + bool program(ParseNode *pn, Value *dst); }; AssignmentOperator @@ -1824,14 +1824,14 @@ ASTSerializer::binop(TokenKind tk, JSOp op) } bool -ASTSerializer::statements(JSParseNode *pn, NodeVector &elts) +ASTSerializer::statements(ParseNode *pn, NodeVector &elts) { JS_ASSERT(pn->isKind(TOK_LC) && pn->isArity(PN_LIST)); if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value elt; if (!sourceElement(next, &elt)) return false; @@ -1842,12 +1842,12 @@ ASTSerializer::statements(JSParseNode *pn, NodeVector &elts) } bool -ASTSerializer::expressions(JSParseNode *pn, NodeVector &elts) +ASTSerializer::expressions(ParseNode *pn, NodeVector &elts) { if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value elt; if (!expression(next, &elt)) return false; @@ -1858,12 +1858,12 @@ ASTSerializer::expressions(JSParseNode *pn, NodeVector &elts) } bool -ASTSerializer::xmls(JSParseNode *pn, NodeVector &elts) +ASTSerializer::xmls(ParseNode *pn, NodeVector &elts) { if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value elt; if (!xml(next, &elt)) return false; @@ -1874,7 +1874,7 @@ ASTSerializer::xmls(JSParseNode *pn, NodeVector &elts) } bool -ASTSerializer::blockStatement(JSParseNode *pn, Value *dst) +ASTSerializer::blockStatement(ParseNode *pn, Value *dst) { JS_ASSERT(pn->isKind(TOK_LC)); @@ -1884,7 +1884,7 @@ ASTSerializer::blockStatement(JSParseNode *pn, Value *dst) } bool -ASTSerializer::program(JSParseNode *pn, Value *dst) +ASTSerializer::program(ParseNode *pn, Value *dst) { JS_ASSERT(pn->pn_pos.begin.lineno == lineno); @@ -1894,14 +1894,14 @@ ASTSerializer::program(JSParseNode *pn, Value *dst) } bool -ASTSerializer::sourceElement(JSParseNode *pn, Value *dst) +ASTSerializer::sourceElement(ParseNode *pn, Value *dst) { /* SpiderMonkey allows declarations even in pure statement contexts. */ return statement(pn, dst); } bool -ASTSerializer::declaration(JSParseNode *pn, Value *dst) +ASTSerializer::declaration(ParseNode *pn, Value *dst) { JS_ASSERT(pn->isKind(TOK_FUNCTION) || pn->isKind(TOK_VAR) || pn->isKind(TOK_LET)); @@ -1919,7 +1919,7 @@ ASTSerializer::declaration(JSParseNode *pn, Value *dst) } bool -ASTSerializer::variableDeclaration(JSParseNode *pn, bool let, Value *dst) +ASTSerializer::variableDeclaration(ParseNode *pn, bool let, Value *dst) { JS_ASSERT(let ? pn->isKind(TOK_LET) : pn->isKind(TOK_VAR)); @@ -1939,7 +1939,7 @@ ASTSerializer::variableDeclaration(JSParseNode *pn, bool let, Value *dst) if (!dtors.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value child; if (!variableDeclarator(next, &kind, &child)) return false; @@ -1950,13 +1950,13 @@ ASTSerializer::variableDeclaration(JSParseNode *pn, bool let, Value *dst) } bool -ASTSerializer::variableDeclarator(JSParseNode *pn, VarDeclKind *pkind, Value *dst) +ASTSerializer::variableDeclarator(ParseNode *pn, VarDeclKind *pkind, Value *dst) { /* A destructuring declarator is always a TOK_ASSIGN. */ JS_ASSERT(pn->isKind(TOK_NAME) || pn->isKind(TOK_ASSIGN)); - JSParseNode *pnleft; - JSParseNode *pnright; + ParseNode *pnleft; + ParseNode *pnright; if (pn->isKind(TOK_NAME)) { pnleft = pn; @@ -1974,14 +1974,14 @@ ASTSerializer::variableDeclarator(JSParseNode *pn, VarDeclKind *pkind, Value *ds } bool -ASTSerializer::letHead(JSParseNode *pn, NodeVector &dtors) +ASTSerializer::letHead(ParseNode *pn, NodeVector &dtors) { if (!dtors.reserve(pn->pn_count)) return false; VarDeclKind kind = VARDECL_LET_HEAD; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value child; /* * Unlike in |variableDeclaration|, this does not update |kind|; since let-heads do @@ -1996,7 +1996,7 @@ ASTSerializer::letHead(JSParseNode *pn, NodeVector &dtors) } bool -ASTSerializer::switchCase(JSParseNode *pn, Value *dst) +ASTSerializer::switchCase(ParseNode *pn, Value *dst) { NodeVector stmts(cx); @@ -2008,14 +2008,14 @@ ASTSerializer::switchCase(JSParseNode *pn, Value *dst) } bool -ASTSerializer::switchStatement(JSParseNode *pn, Value *dst) +ASTSerializer::switchStatement(ParseNode *pn, Value *dst) { Value disc; if (!expression(pn->pn_left, &disc)) return false; - JSParseNode *listNode; + ParseNode *listNode; bool lexical; if (pn->pn_right->isKind(TOK_LEXICALSCOPE)) { @@ -2030,7 +2030,7 @@ ASTSerializer::switchStatement(JSParseNode *pn, Value *dst) if (!cases.reserve(listNode->pn_count)) return false; - for (JSParseNode *next = listNode->pn_head; next; next = next->pn_next) { + for (ParseNode *next = listNode->pn_head; next; next = next->pn_next) { Value child; #ifdef __GNUC__ /* quell GCC overwarning */ child = UndefinedValue(); @@ -2044,7 +2044,7 @@ ASTSerializer::switchStatement(JSParseNode *pn, Value *dst) } bool -ASTSerializer::catchClause(JSParseNode *pn, Value *dst) +ASTSerializer::catchClause(ParseNode *pn, Value *dst) { Value var, guard, body; @@ -2055,7 +2055,7 @@ ASTSerializer::catchClause(JSParseNode *pn, Value *dst) } bool -ASTSerializer::tryStatement(JSParseNode *pn, Value *dst) +ASTSerializer::tryStatement(ParseNode *pn, Value *dst) { Value body; if (!statement(pn->pn_kid1, &body)) @@ -2066,7 +2066,7 @@ ASTSerializer::tryStatement(JSParseNode *pn, Value *dst) if (!clauses.reserve(pn->pn_kid2->pn_count)) return false; - for (JSParseNode *next = pn->pn_kid2->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_kid2->pn_head; next; next = next->pn_next) { Value clause; if (!catchClause(next->pn_expr, &clause)) return false; @@ -2080,7 +2080,7 @@ ASTSerializer::tryStatement(JSParseNode *pn, Value *dst) } bool -ASTSerializer::forInit(JSParseNode *pn, Value *dst) +ASTSerializer::forInit(ParseNode *pn, Value *dst) { if (!pn) { dst->setMagic(JS_SERIALIZE_NO_NODE); @@ -2095,7 +2095,7 @@ ASTSerializer::forInit(JSParseNode *pn, Value *dst) } bool -ASTSerializer::statement(JSParseNode *pn, Value *dst) +ASTSerializer::statement(ParseNode *pn, Value *dst) { JS_CHECK_RECURSION(cx, return false); switch (pn->getKind()) { @@ -2173,7 +2173,7 @@ ASTSerializer::statement(JSParseNode *pn, Value *dst) case TOK_FOR: { - JSParseNode *head = pn->pn_left; + ParseNode *head = pn->pn_left; Value stmt; if (!statement(pn->pn_right, &stmt)) @@ -2206,8 +2206,8 @@ ASTSerializer::statement(JSParseNode *pn, Value *dst) { LOCAL_ASSERT(pn->pn_count == 2); - JSParseNode *prelude = pn->pn_head; - JSParseNode *loop = prelude->pn_next; + ParseNode *prelude = pn->pn_head; + ParseNode *loop = prelude->pn_next; LOCAL_ASSERT(prelude->isKind(TOK_VAR) && loop->isKind(TOK_FOR)); @@ -2215,7 +2215,7 @@ ASTSerializer::statement(JSParseNode *pn, Value *dst) if (!variableDeclaration(prelude, false, &var)) return false; - JSParseNode *head = loop->pn_left; + ParseNode *head = loop->pn_left; JS_ASSERT(head->isKind(TOK_IN)); bool isForEach = loop->pn_iflags & JSITER_FOREACH; @@ -2279,7 +2279,7 @@ ASTSerializer::statement(JSParseNode *pn, Value *dst) } bool -ASTSerializer::leftAssociate(JSParseNode *pn, Value *dst) +ASTSerializer::leftAssociate(ParseNode *pn, Value *dst) { JS_ASSERT(pn->isArity(PN_LIST)); JS_ASSERT(pn->pn_count >= 1); @@ -2288,16 +2288,16 @@ ASTSerializer::leftAssociate(JSParseNode *pn, Value *dst) bool lor = tk == TOK_OR; bool logop = lor || (tk == TOK_AND); - JSParseNode *head = pn->pn_head; + ParseNode *head = pn->pn_head; Value left; if (!expression(head, &left)) return false; - for (JSParseNode *next = head->pn_next; next; next = next->pn_next) { + for (ParseNode *next = head->pn_next; next; next = next->pn_next) { Value right; if (!expression(next, &right)) return false; - TokenPos subpos = { pn->pn_pos.begin, next->pn_pos.end }; + TokenPos subpos(pn->pn_pos.begin, next->pn_pos.end); if (logop) { if (!builder.logicalExpression(lor, left, right, &subpos, &left)) @@ -2316,11 +2316,11 @@ ASTSerializer::leftAssociate(JSParseNode *pn, Value *dst) } bool -ASTSerializer::comprehensionBlock(JSParseNode *pn, Value *dst) +ASTSerializer::comprehensionBlock(ParseNode *pn, Value *dst) { LOCAL_ASSERT(pn->isArity(PN_BINARY)); - JSParseNode *in = pn->pn_left; + ParseNode *in = pn->pn_left; LOCAL_ASSERT(in && in->isKind(TOK_IN)); @@ -2333,13 +2333,13 @@ ASTSerializer::comprehensionBlock(JSParseNode *pn, Value *dst) } bool -ASTSerializer::comprehension(JSParseNode *pn, Value *dst) +ASTSerializer::comprehension(ParseNode *pn, Value *dst) { LOCAL_ASSERT(pn->isKind(TOK_FOR)); NodeVector blocks(cx); - JSParseNode *next = pn; + ParseNode *next = pn; while (next->isKind(TOK_FOR)) { Value block; if (!comprehensionBlock(next, &block) || !blocks.append(block)) @@ -2368,13 +2368,13 @@ ASTSerializer::comprehension(JSParseNode *pn, Value *dst) } bool -ASTSerializer::generatorExpression(JSParseNode *pn, Value *dst) +ASTSerializer::generatorExpression(ParseNode *pn, Value *dst) { LOCAL_ASSERT(pn->isKind(TOK_FOR)); NodeVector blocks(cx); - JSParseNode *next = pn; + ParseNode *next = pn; while (next->isKind(TOK_FOR)) { Value block; if (!comprehensionBlock(next, &block) || !blocks.append(block)) @@ -2401,7 +2401,7 @@ ASTSerializer::generatorExpression(JSParseNode *pn, Value *dst) } bool -ASTSerializer::expression(JSParseNode *pn, Value *dst) +ASTSerializer::expression(ParseNode *pn, Value *dst) { JS_CHECK_RECURSION(cx, return false); switch (pn->getKind()) { @@ -2509,7 +2509,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) return generatorExpression(pn->generatorExpr(), dst); #endif - JSParseNode *next = pn->pn_head; + ParseNode *next = pn->pn_head; Value callee; if (!expression(next, &callee)) @@ -2559,7 +2559,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { if (next->isKind(TOK_COMMA)) { elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE)); } else { @@ -2584,7 +2584,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { Value prop; if (!property(next, &prop)) return false; @@ -2649,7 +2649,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) LOCAL_ASSERT(pn->isArity(PN_NAME) || pn->isArity(PN_BINARY)); - JSParseNode *pnleft; + ParseNode *pnleft; bool computed; if (pn->isArity(PN_BINARY)) { @@ -2676,7 +2676,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) case TOK_AT: { Value expr; - JSParseNode *kid = pn->pn_kid; + ParseNode *kid = pn->pn_kid; bool computed = ((!kid->isKind(TOK_NAME) || !kid->isOp(JSOP_QNAMEPART)) && !kid->isKind(TOK_DBLCOLON) && !kid->isKind(TOK_ANYNAME)); @@ -2703,7 +2703,7 @@ ASTSerializer::expression(JSParseNode *pn, Value *dst) } bool -ASTSerializer::xml(JSParseNode *pn, Value *dst) +ASTSerializer::xml(ParseNode *pn, Value *dst) { JS_CHECK_RECURSION(cx, return false); switch (pn->getKind()) { @@ -2796,7 +2796,7 @@ ASTSerializer::xml(JSParseNode *pn, Value *dst) } bool -ASTSerializer::propertyName(JSParseNode *pn, Value *dst) +ASTSerializer::propertyName(ParseNode *pn, Value *dst) { if (pn->isKind(TOK_NAME)) return identifier(pn, dst); @@ -2807,7 +2807,7 @@ ASTSerializer::propertyName(JSParseNode *pn, Value *dst) } bool -ASTSerializer::property(JSParseNode *pn, Value *dst) +ASTSerializer::property(ParseNode *pn, Value *dst) { PropKind kind; switch (pn->getOp()) { @@ -2834,7 +2834,7 @@ ASTSerializer::property(JSParseNode *pn, Value *dst) } bool -ASTSerializer::literal(JSParseNode *pn, Value *dst) +ASTSerializer::literal(ParseNode *pn, Value *dst) { Value val; switch (pn->getKind()) { @@ -2878,7 +2878,7 @@ ASTSerializer::literal(JSParseNode *pn, Value *dst) } bool -ASTSerializer::arrayPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) +ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst) { JS_ASSERT(pn->isKind(TOK_RB)); @@ -2886,7 +2886,7 @@ ASTSerializer::arrayPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { if (next->isKind(TOK_COMMA)) { elts.infallibleAppend(MagicValue(JS_SERIALIZE_NO_NODE)); } else { @@ -2901,7 +2901,7 @@ ASTSerializer::arrayPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) } bool -ASTSerializer::objectPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) +ASTSerializer::objectPattern(ParseNode *pn, VarDeclKind *pkind, Value *dst) { JS_ASSERT(pn->isKind(TOK_RC)); @@ -2909,7 +2909,7 @@ ASTSerializer::objectPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) if (!elts.reserve(pn->pn_count)) return false; - for (JSParseNode *next = pn->pn_head; next; next = next->pn_next) { + for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { LOCAL_ASSERT(next->isOp(JSOP_INITPROP)); Value key, patt, prop; @@ -2926,7 +2926,7 @@ ASTSerializer::objectPattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) } bool -ASTSerializer::pattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst) +ASTSerializer::pattern(ParseNode *pn, VarDeclKind *pkind, Value *dst) { JS_CHECK_RECURSION(cx, return false); switch (pn->getKind()) { @@ -2953,7 +2953,7 @@ ASTSerializer::identifier(JSAtom *atom, TokenPos *pos, Value *dst) } bool -ASTSerializer::identifier(JSParseNode *pn, Value *dst) +ASTSerializer::identifier(ParseNode *pn, Value *dst) { LOCAL_ASSERT(pn->isArity(PN_NAME) || pn->isArity(PN_NULLARY)); LOCAL_ASSERT(pn->pn_atom); @@ -2962,7 +2962,7 @@ ASTSerializer::identifier(JSParseNode *pn, Value *dst) } bool -ASTSerializer::function(JSParseNode *pn, ASTType type, Value *dst) +ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst) { JSFunction *func = (JSFunction *)pn->pn_funbox->object; @@ -2986,9 +2986,9 @@ ASTSerializer::function(JSParseNode *pn, ASTType type, Value *dst) NodeVector args(cx); - JSParseNode *argsAndBody = pn->pn_body->isKind(TOK_UPVARS) - ? pn->pn_body->pn_tree - : pn->pn_body; + ParseNode *argsAndBody = pn->pn_body->isKind(TOK_UPVARS) + ? pn->pn_body->pn_tree + : pn->pn_body; Value body; return functionArgsAndBody(argsAndBody, args, &body) && @@ -2996,10 +2996,10 @@ ASTSerializer::function(JSParseNode *pn, ASTType type, Value *dst) } bool -ASTSerializer::functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *body) +ASTSerializer::functionArgsAndBody(ParseNode *pn, NodeVector &args, Value *body) { - JSParseNode *pnargs; - JSParseNode *pnbody; + ParseNode *pnargs; + ParseNode *pnbody; /* Extract the args and body separately. */ if (pn->isKind(TOK_ARGSBODY)) { @@ -3010,11 +3010,11 @@ ASTSerializer::functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *bod pnbody = pn; } - JSParseNode *pndestruct; + ParseNode *pndestruct; /* Extract the destructuring assignments. */ if (pnbody->isArity(PN_LIST) && (pnbody->pn_xflags & PNX_DESTRUCT)) { - JSParseNode *head = pnbody->pn_head; + ParseNode *head = pnbody->pn_head; LOCAL_ASSERT(head && head->isKind(TOK_SEMI)); pndestruct = head->pn_kid; @@ -3031,7 +3031,7 @@ ASTSerializer::functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *bod case TOK_SEQ: /* expression closure with destructured args */ { - JSParseNode *pnstart = pnbody->pn_head->pn_next; + ParseNode *pnstart = pnbody->pn_head->pn_next; LOCAL_ASSERT(pnstart && pnstart->isKind(TOK_RETURN)); return functionArgs(pn, pnargs, pndestruct, pnbody, args) && @@ -3040,7 +3040,7 @@ ASTSerializer::functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *bod case TOK_LC: /* statement closure */ { - JSParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT) + ParseNode *pnstart = (pnbody->pn_xflags & PNX_DESTRUCT) ? pnbody->pn_head->pn_next : pnbody->pn_head; @@ -3054,12 +3054,12 @@ ASTSerializer::functionArgsAndBody(JSParseNode *pn, NodeVector &args, Value *bod } bool -ASTSerializer::functionArgs(JSParseNode *pn, JSParseNode *pnargs, JSParseNode *pndestruct, - JSParseNode *pnbody, NodeVector &args) +ASTSerializer::functionArgs(ParseNode *pn, ParseNode *pnargs, ParseNode *pndestruct, + ParseNode *pnbody, NodeVector &args) { uint32 i = 0; - JSParseNode *arg = pnargs ? pnargs->pn_head : NULL; - JSParseNode *destruct = pndestruct ? pndestruct->pn_head : NULL; + ParseNode *arg = pnargs ? pnargs->pn_head : NULL; + ParseNode *destruct = pndestruct ? pndestruct->pn_head : NULL; Value node; /* @@ -3100,12 +3100,12 @@ ASTSerializer::functionArgs(JSParseNode *pn, JSParseNode *pnargs, JSParseNode *p } bool -ASTSerializer::functionBody(JSParseNode *pn, TokenPos *pos, Value *dst) +ASTSerializer::functionBody(ParseNode *pn, TokenPos *pos, Value *dst) { NodeVector elts(cx); /* We aren't sure how many elements there are up front, so we'll check each append. */ - for (JSParseNode *next = pn; next; next = next->pn_next) { + for (ParseNode *next = pn; next; next = next->pn_next) { Value child; if (!sourceElement(next, &child) || !elts.append(child)) return false; @@ -3221,7 +3221,7 @@ reflect_parse(JSContext *cx, uint32 argc, jsval *vp) serialize.setParser(&parser); - JSParseNode *pn = parser.parse(NULL); + ParseNode *pn = parser.parse(NULL); if (!pn) return JS_FALSE; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 57c353c6505c..ae296c6b1491 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -80,6 +80,7 @@ using namespace js; using namespace js::gc; +using namespace js::frontend; namespace js { @@ -1097,7 +1098,7 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom } JSScript * -JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) +JSScript::NewScriptFromCG(JSContext *cx, CodeGenerator *cg) { uint32 mainLength, prologLength, nsrcnotes, nfixed; JSScript *script; @@ -1162,10 +1163,10 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) script->sourceMap = (jschar *) cg->parser->tokenStream.releaseSourceMap(); - if (!js_FinishTakingSrcNotes(cx, cg, script->notes())) + if (!FinishTakingSrcNotes(cx, cg, script->notes())) return NULL; if (cg->ntrynotes != 0) - js_FinishTakingTryNotes(cg, script->trynotes()); + FinishTakingTryNotes(cg, script->trynotes()); if (cg->objectList.length != 0) cg->objectList.finish(script->objects()); if (cg->regexpList.length != 0) @@ -1470,13 +1471,6 @@ js_FramePCToLineNumber(JSContext *cx, StackFrame *fp, jsbytecode *pc) uintN js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) { - JSOp op; - JSFunction *fun; - uintN lineno; - ptrdiff_t offset, target; - jssrcnote *sn; - JSSrcNoteType type; - /* Cope with StackFrame.pc value prior to entering js_Interpret. */ if (!pc) return 0; @@ -1485,10 +1479,11 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) * Special case: function definition needs no line number note because * the function's script contains its starting line number. */ - op = js_GetOpcode(cx, script, pc); + JSOp op = js_GetOpcode(cx, script, pc); if (js_CodeSpec[op].format & JOF_INDEXBASE) pc += js_CodeSpec[op].length; if (*pc == JSOP_DEFFUN) { + JSFunction *fun; GET_FUNCTION_FROM_BYTECODE(script, pc, 0, fun); return fun->script()->lineno; } @@ -1498,12 +1493,12 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) * keeping track of line-number notes, until we pass the note for pc's * offset within script->code. */ - lineno = script->lineno; - offset = 0; - target = pc - script->code; - for (sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { + uintN lineno = script->lineno; + ptrdiff_t offset = 0; + ptrdiff_t target = pc - script->code; + for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { offset += SN_DELTA(sn); - type = (JSSrcNoteType) SN_TYPE(sn); + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE) { if (offset <= target) lineno = (uintN) js_GetSrcNoteOffset(sn, 0); @@ -1523,16 +1518,11 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc) jsbytecode * js_LineNumberToPC(JSScript *script, uintN target) { - ptrdiff_t offset, best; - uintN lineno, bestdiff, diff; - jssrcnote *sn; - JSSrcNoteType type; - - offset = 0; - best = -1; - lineno = script->lineno; - bestdiff = SN_LINE_LIMIT; - for (sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { + ptrdiff_t offset = 0; + ptrdiff_t best = -1; + uintN lineno = script->lineno; + uintN bestdiff = SN_LINE_LIMIT; + for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { /* * Exact-match only if offset is not in the prolog; otherwise use * nearest greater-or-equal line number match. @@ -1540,14 +1530,14 @@ js_LineNumberToPC(JSScript *script, uintN target) if (lineno == target && offset >= ptrdiff_t(script->mainOffset)) goto out; if (lineno >= target) { - diff = lineno - target; + uintN diff = lineno - target; if (diff < bestdiff) { bestdiff = diff; best = offset; } } offset += SN_DELTA(sn); - type = (JSSrcNoteType) SN_TYPE(sn); + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE) { lineno = (uintN) js_GetSrcNoteOffset(sn, 0); } else if (type == SRC_NEWLINE) { @@ -1563,18 +1553,11 @@ out: JS_FRIEND_API(uintN) js_GetScriptLineExtent(JSScript *script) { - - bool counting; - uintN lineno; - uintN maxLineNo; - jssrcnote *sn; - JSSrcNoteType type; - - lineno = script->lineno; - maxLineNo = 0; - counting = true; - for (sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - type = (JSSrcNoteType) SN_TYPE(sn); + uintN lineno = script->lineno; + uintN maxLineNo = 0; + bool counting = true; + for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE) { if (maxLineNo < lineno) maxLineNo = lineno; diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 68e78febebc1..a41433113509 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -447,7 +447,7 @@ struct JSScript : public js::gc::Cell { uint16 nClosedArgs, uint16 nClosedVars, uint32 nTypeSets, JSVersion version); - static JSScript *NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg); + static JSScript *NewScriptFromCG(JSContext *cx, js::CodeGenerator *cg); #ifdef JS_CRASH_DIAGNOSTICS /* diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 880783dffba9..b75e61298320 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1524,10 +1524,8 @@ BuildFlatMatchArray(JSContext *cx, JSString *textstr, const FlatMatch &fm, Value vp->setObject(*obj); return obj->defineElement(cx, 0, StringValue(fm.pattern())) && - obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.indexAtom), - Int32Value(fm.match())) && - obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.inputAtom), - StringValue(textstr)); + obj->defineProperty(cx, cx->runtime->atomState.indexAtom, Int32Value(fm.match())) && + obj->defineProperty(cx, cx->runtime->atomState.inputAtom, StringValue(textstr)); } typedef JSObject **MatchArgType; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index fb1a7870f94c..881cf4e5e25d 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -10909,30 +10909,74 @@ TraceRecorder::getClassPrototype(JSObject* ctor, LIns*& proto_ins) return RECORD_CONTINUE; } -RecordingStatus -TraceRecorder::getClassPrototype(JSProtoKey key, LIns*& proto_ins) +static inline void +AssertValidPrototype(JSObject *proto, JSProtoKey key, DebugOnly localtm, + JSContext *cx) { #ifdef DEBUG - TraceMonitor &localtm = *traceMonitor; + /* This shouldn't have reentered. */ + JS_ASSERT(localtm->recorder); + + /* Double-check for a matching emptyShape. */ + JS_ASSERT(proto->isNative()); + JS_ASSERT(proto->getNewType(cx)->emptyShapes); + EmptyShape *empty = proto->getNewType(cx)->emptyShapes[0]; + JS_ASSERT(empty); + JS_ASSERT(JSCLASS_CACHED_PROTO_KEY(empty->getClass()) == key); #endif +} - JSObject* proto; - if (!js_GetClassPrototype(cx, globalObj, key, &proto)) - RETURN_ERROR("error in js_GetClassPrototype"); +RecordingStatus +TraceRecorder::getObjectPrototype(LIns*& proto_ins) +{ + DebugOnly localtm = traceMonitor; - // This should not have reentered. - JS_ASSERT(localtm.recorder); + JSObject *proto = globalObj->asGlobal()->getOrCreateObjectPrototype(cx); + if (!proto) + RETURN_ERROR("error getting Object.prototype"); + AssertValidPrototype(proto, JSProto_Object, localtm, cx); -#ifdef DEBUG - /* Double-check that a native proto has a matching emptyShape. */ - if (key != JSProto_Array) { - JS_ASSERT(proto->isNative()); - JS_ASSERT(proto->getNewType(cx)->emptyShapes); - EmptyShape *empty = proto->getNewType(cx)->emptyShapes[0]; - JS_ASSERT(empty); - JS_ASSERT(JSCLASS_CACHED_PROTO_KEY(empty->getClass()) == key); - } -#endif + proto_ins = w.immpObjGC(proto); + return RECORD_CONTINUE; +} + +RecordingStatus +TraceRecorder::getFunctionPrototype(LIns*& proto_ins) +{ + DebugOnly localtm = traceMonitor; + + JSObject *proto = globalObj->asGlobal()->getOrCreateFunctionPrototype(cx); + if (!proto) + RETURN_ERROR("error getting Function.prototype"); + AssertValidPrototype(proto, JSProto_Function, localtm, cx); + + proto_ins = w.immpObjGC(proto); + return RECORD_CONTINUE; +} + +RecordingStatus +TraceRecorder::getArrayPrototype(LIns*& proto_ins) +{ + DebugOnly localtm = traceMonitor; + + JSObject *proto = globalObj->asGlobal()->getOrCreateArrayPrototype(cx); + if (!proto) + RETURN_ERROR("error getting Array.prototype"); + AssertValidPrototype(proto, JSProto_Array, localtm, cx); + + proto_ins = w.immpObjGC(proto); + return RECORD_CONTINUE; +} + +RecordingStatus +TraceRecorder::getRegExpPrototype(LIns*& proto_ins) +{ + DebugOnly localtm = traceMonitor; + + JSObject *proto = globalObj->asGlobal()->getOrCreateRegExpPrototype(cx); + if (!proto) + RETURN_ERROR("error getting RegExp.prototype"); + AssertValidPrototype(proto, JSProto_RegExp, localtm, cx); proto_ins = w.immpObjGC(proto); return RECORD_CONTINUE; @@ -11631,7 +11675,7 @@ DeleteIntKey(JSContext* cx, JSObject* obj, int32 i, JSBool strict) } } - if (!obj->deleteProperty(cx, id, &v, strict)) + if (!obj->deleteGeneric(cx, id, &v, strict)) SetBuiltinError(tm); return v.toBoolean(); } @@ -11653,7 +11697,7 @@ DeleteStrKey(JSContext* cx, JSObject* obj, JSString* str, JSBool strict) * jsatominlines.h) that helper early-returns if the computed property name * string is already atomized, and we are *not* on a perf-critical path! */ - if (!js_ValueToStringId(cx, StringValue(str), &id) || !obj->deleteProperty(cx, id, &v, strict)) + if (!js_ValueToStringId(cx, StringValue(str), &id) || !obj->deleteGeneric(cx, id, &v, strict)) SetBuiltinError(tm); return v.toBoolean(); } @@ -12853,7 +12897,7 @@ SetPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, Value* vp, JSB LeaveTraceIfGlobalObject(cx, obj); jsid id; - if (!RootedStringToId(cx, namep, &id) || !obj->setProperty(cx, id, vp, strict)) { + if (!RootedStringToId(cx, namep, &id) || !obj->setGeneric(cx, id, vp, strict)) { SetBuiltinError(tm); return false; } @@ -12872,7 +12916,7 @@ InitPropertyByName(JSContext* cx, JSObject* obj, JSString** namep, ValueArgType jsid id; if (!RootedStringToId(cx, namep, &id) || - !obj->defineProperty(cx, id, ValueArgToConstRef(arg), NULL, NULL, JSPROP_ENUMERATE)) { + !obj->defineGeneric(cx, id, ValueArgToConstRef(arg), NULL, NULL, JSPROP_ENUMERATE)) { SetBuiltinError(tm); return JS_FALSE; } @@ -12913,7 +12957,7 @@ SetPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, Value* vp, JSBool LeaveTraceIfGlobalObject(cx, obj); AutoIdRooter idr(cx); - if (!js_Int32ToId(cx, index, idr.addr()) || !obj->setProperty(cx, idr.id(), vp, strict)) { + if (!js_Int32ToId(cx, index, idr.addr()) || !obj->setGeneric(cx, idr.id(), vp, strict)) { SetBuiltinError(tm); return false; } @@ -12931,7 +12975,7 @@ InitPropertyByIndex(JSContext* cx, JSObject* obj, int32 index, ValueArgType arg) AutoIdRooter idr(cx); if (!js_Int32ToId(cx, index, idr.addr()) || - !obj->defineProperty(cx, idr.id(), ValueArgToConstRef(arg), NULL, NULL, JSPROP_ENUMERATE)) { + !obj->defineGeneric(cx, idr.id(), ValueArgToConstRef(arg), NULL, NULL, JSPROP_ENUMERATE)) { SetBuiltinError(tm); return JS_FALSE; } @@ -14334,15 +14378,16 @@ TraceRecorder::record_JSOP_NEWINIT() hadNewInit = true; JSProtoKey key = JSProtoKey(cx->regs().pc[1]); + JS_ASSERT(key == JSProto_Array || key == JSProto_Object); - LIns* proto_ins; - CHECK_STATUS_A(getClassPrototype(key, proto_ins)); - + LIns* proto_ins = NULL; LIns *v_ins; if (key == JSProto_Array) { + CHECK_STATUS_A(getArrayPrototype(proto_ins)); LIns *args[] = { proto_ins, cx_ins }; v_ins = w.call(&NewDenseEmptyArray_ci, args); } else { + CHECK_STATUS_A(getObjectPrototype(proto_ins)); LIns *args[] = { w.immpNull(), proto_ins, cx_ins }; v_ins = w.call(&js_InitializerObject_ci, args); } @@ -14356,8 +14401,8 @@ TraceRecorder::record_JSOP_NEWARRAY() { initDepth++; - LIns* proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_Array, proto_ins)); + LIns* proto_ins = NULL; + CHECK_STATUS_A(getArrayPrototype(proto_ins)); unsigned count = GET_UINT24(cx->regs().pc); LIns *args[] = { proto_ins, w.immi(count), cx_ins }; @@ -14373,8 +14418,8 @@ TraceRecorder::record_JSOP_NEWOBJECT() { initDepth++; - LIns* proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_Object, proto_ins)); + LIns* proto_ins = NULL; + CHECK_STATUS_A(getObjectPrototype(proto_ins)); JSObject* baseobj = cx->fp()->script()->getObject(getFullIndex(0)); @@ -15279,8 +15324,8 @@ TraceRecorder::record_JSOP_LAMBDA() } } - LIns *proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); + LIns *proto_ins = NULL; + CHECK_STATUS_A(getFunctionPrototype(proto_ins)); LIns* args[] = { w.immpObjGC(globalObj), proto_ins, w.immpFunGC(fun), cx_ins }; LIns* x = w.call(&js_NewNullClosure_ci, args); @@ -15294,8 +15339,8 @@ TraceRecorder::record_JSOP_LAMBDA() if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH)) RETURN_STOP_A("Unable to trace creating lambda in let"); - LIns *proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); + LIns *proto_ins = NULL; + CHECK_STATUS_A(getFunctionPrototype(proto_ins)); LIns* scopeChain_ins = scopeChain(); JS_ASSERT(scopeChain_ins); LIns* args[] = { proto_ins, scopeChain_ins, w.nameImmpNonGC(fun), cx_ins }; @@ -15465,8 +15510,8 @@ TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj) JSFunction* fun = obj->getFunctionPrivate(); if (fun->isNullClosure() && fun->getParent() == globalObj) { - LIns *proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins)); + LIns *proto_ins = NULL; + CHECK_STATUS_A(getFunctionPrototype(proto_ins)); LIns* args[] = { w.immpObjGC(globalObj), proto_ins, w.immpFunGC(fun), cx_ins }; LIns* x = w.call(&js_NewNullClosure_ci, args); @@ -15588,8 +15633,8 @@ TraceRecorder::record_JSOP_REGEXP() JSScript* script = fp->script(); unsigned index = atoms - script->atoms + GET_INDEX(cx->regs().pc); - LIns* proto_ins; - CHECK_STATUS_A(getClassPrototype(JSProto_RegExp, proto_ins)); + LIns* proto_ins = NULL; + CHECK_STATUS_A(getRegExpPrototype(proto_ins)); LIns* args[] = { proto_ins, diff --git a/js/src/jstracer.h b/js/src/jstracer.h index ce8eeb10fd4f..381d15fa4431 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -1489,10 +1489,14 @@ class TraceRecorder unsigned *depthp); JS_REQUIRES_STACK nanojit::LIns* guardArgsLengthNotAssigned(nanojit::LIns* argsobj_ins); JS_REQUIRES_STACK void guardNotHole(nanojit::LIns* argsobj_ins, nanojit::LIns* ids_ins); + JS_REQUIRES_STACK RecordingStatus getClassPrototype(JSObject* ctor, nanojit::LIns*& proto_ins); - JS_REQUIRES_STACK RecordingStatus getClassPrototype(JSProtoKey key, - nanojit::LIns*& proto_ins); + JS_REQUIRES_STACK RecordingStatus getObjectPrototype(nanojit::LIns*& proto_ins); + JS_REQUIRES_STACK RecordingStatus getFunctionPrototype(nanojit::LIns*& proto_ins); + JS_REQUIRES_STACK RecordingStatus getArrayPrototype(nanojit::LIns*& proto_ins); + JS_REQUIRES_STACK RecordingStatus getRegExpPrototype(nanojit::LIns*& proto_ins); + JS_REQUIRES_STACK RecordingStatus newArray(JSObject* ctor, uint32 argc, Value* argv, Value* rval); JS_REQUIRES_STACK RecordingStatus newString(JSObject* ctor, uint32 argc, Value* argv, diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index e4f721a4677a..ff80a9e95e10 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -325,8 +325,8 @@ ArrayBuffer::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, } JSBool -ArrayBuffer::obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, - PropertyOp getter, StrictPropertyOp setter, uintN attrs) +ArrayBuffer::obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) return true; @@ -337,6 +337,13 @@ ArrayBuffer::obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Val return js_DefineProperty(cx, delegate, id, v, getter, setter, attrs); } +JSBool +ArrayBuffer::obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) +{ + return obj_defineGeneric(cx, obj, ATOM_TO_JSID(name), v, getter, setter, attrs); +} + JSBool ArrayBuffer::obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) @@ -351,7 +358,7 @@ JSBool ArrayBuffer::obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) { - return obj_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); + return obj_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); } JSBool @@ -392,7 +399,7 @@ ArrayBuffer::obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, Sp } JSBool -ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +ArrayBuffer::obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) return true; @@ -445,6 +452,12 @@ ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, J return js_SetPropertyHelper(cx, delegate, id, 0, vp, strict); } +JSBool +ArrayBuffer::obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) +{ + return obj_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict); +} + JSBool ArrayBuffer::obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict) { @@ -458,11 +471,11 @@ ArrayBuffer::obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *v JSBool ArrayBuffer::obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict) { - return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); + return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); } JSBool -ArrayBuffer::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +ArrayBuffer::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) { *attrsp = JSPROP_PERMANENT | JSPROP_READONLY; @@ -475,6 +488,12 @@ ArrayBuffer::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *att return js_GetAttributes(cx, delegate, id, attrsp); } +JSBool +ArrayBuffer::obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return obj_getGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + JSBool ArrayBuffer::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { @@ -487,11 +506,11 @@ ArrayBuffer::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index JSBool ArrayBuffer::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } JSBool -ArrayBuffer::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +ArrayBuffer::obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -505,6 +524,12 @@ ArrayBuffer::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *att return js_SetAttributes(cx, delegate, id, attrsp); } +JSBool +ArrayBuffer::obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return obj_setGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + JSBool ArrayBuffer::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { @@ -517,11 +542,11 @@ ArrayBuffer::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index JSBool ArrayBuffer::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return obj_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return obj_setGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } JSBool -ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) +ArrayBuffer::obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) { rval->setBoolean(false); @@ -534,6 +559,12 @@ ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rv return js_DeleteProperty(cx, delegate, id, rval, strict); } +JSBool +ArrayBuffer::obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) +{ + return obj_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict); +} + JSBool ArrayBuffer::obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) { @@ -546,7 +577,7 @@ ArrayBuffer::obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value JSBool ArrayBuffer::obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return obj_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return obj_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); } JSBool @@ -722,7 +753,7 @@ TypedArray::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, } JSBool -TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +TypedArray::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) ? JSPROP_PERMANENT | JSPROP_READONLY @@ -730,6 +761,13 @@ TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attr return true; } +JSBool +TypedArray::obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE; + return true; +} + JSBool TypedArray::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { @@ -740,11 +778,18 @@ TypedArray::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, JSBool TypedArray::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return obj_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } JSBool -TypedArray::obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +TypedArray::obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +{ + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; +} + +JSBool +TypedArray::obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); return false; @@ -760,7 +805,8 @@ TypedArray::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, JSBool TypedArray::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return obj_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS); + return false; } /* static */ int @@ -1088,7 +1134,7 @@ class TypedArrayTemplate } static JSBool - obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) + obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { JSObject *tarray = getTypedArray(obj); JS_ASSERT(tarray); @@ -1113,6 +1159,12 @@ class TypedArrayTemplate return setElementTail(cx, tarray, index, vp, strict); } + static JSBool + obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) + { + return obj_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict); + } + static JSBool obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict) { @@ -1135,18 +1187,25 @@ class TypedArrayTemplate static JSBool obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict) { - return obj_setProperty(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); + return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict); } static JSBool - obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, - PropertyOp getter, StrictPropertyOp setter, uintN attrs) + obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) { if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) return true; Value tmp = *v; - return obj_setProperty(cx, obj, id, &tmp, false); + return obj_setGeneric(cx, obj, id, &tmp, false); + } + + static JSBool + obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) + { + return obj_defineGeneric(cx, obj, ATOM_TO_JSID(name), v, getter, setter, attrs); } static JSBool @@ -1161,11 +1220,11 @@ class TypedArrayTemplate obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) { - return obj_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); + return obj_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); } static JSBool - obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) + obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { rval->setBoolean(false); @@ -1184,6 +1243,12 @@ class TypedArrayTemplate return true; } + static JSBool + obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) + { + return obj_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict); + } + static JSBool obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) { @@ -1202,7 +1267,7 @@ class TypedArrayTemplate static JSBool obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return obj_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return obj_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); } static JSBool @@ -2033,7 +2098,7 @@ Class js::ArrayBufferClass = { ArrayBuffer::obj_lookupProperty, ArrayBuffer::obj_lookupElement, ArrayBuffer::obj_lookupSpecial, - ArrayBuffer::obj_defineProperty, + ArrayBuffer::obj_defineGeneric, ArrayBuffer::obj_defineProperty, ArrayBuffer::obj_defineElement, ArrayBuffer::obj_defineSpecial, @@ -2041,19 +2106,19 @@ Class js::ArrayBufferClass = { ArrayBuffer::obj_getProperty, ArrayBuffer::obj_getElement, ArrayBuffer::obj_getSpecial, - ArrayBuffer::obj_setProperty, + ArrayBuffer::obj_setGeneric, ArrayBuffer::obj_setProperty, ArrayBuffer::obj_setElement, ArrayBuffer::obj_setSpecial, - ArrayBuffer::obj_getAttributes, - ArrayBuffer::obj_getAttributes, + ArrayBuffer::obj_getGenericAttributes, + ArrayBuffer::obj_getPropertyAttributes, ArrayBuffer::obj_getElementAttributes, ArrayBuffer::obj_getSpecialAttributes, - ArrayBuffer::obj_setAttributes, - ArrayBuffer::obj_setAttributes, + ArrayBuffer::obj_setGenericAttributes, + ArrayBuffer::obj_setPropertyAttributes, ArrayBuffer::obj_setElementAttributes, ArrayBuffer::obj_setSpecialAttributes, - ArrayBuffer::obj_deleteProperty, + ArrayBuffer::obj_deleteGeneric, ArrayBuffer::obj_deleteProperty, ArrayBuffer::obj_deleteElement, ArrayBuffer::obj_deleteSpecial, @@ -2145,27 +2210,27 @@ JSFunctionSpec _typedArray::jsfuncs[] = { \ _typedArray::obj_lookupProperty, \ _typedArray::obj_lookupElement, \ _typedArray::obj_lookupSpecial, \ - _typedArray::obj_defineProperty, \ + _typedArray::obj_defineGeneric, \ _typedArray::obj_defineProperty, \ _typedArray::obj_defineElement, \ _typedArray::obj_defineSpecial, \ - _typedArray::obj_getGeneric, \ + _typedArray::obj_getGeneric, \ _typedArray::obj_getProperty, \ _typedArray::obj_getElement, \ _typedArray::obj_getSpecial, \ - _typedArray::obj_setProperty, \ + _typedArray::obj_setGeneric, \ _typedArray::obj_setProperty, \ _typedArray::obj_setElement, \ _typedArray::obj_setSpecial, \ - _typedArray::obj_getAttributes, \ - _typedArray::obj_getAttributes, \ + _typedArray::obj_getGenericAttributes, \ + _typedArray::obj_getPropertyAttributes, \ _typedArray::obj_getElementAttributes, \ _typedArray::obj_getSpecialAttributes, \ - _typedArray::obj_setAttributes, \ - _typedArray::obj_setAttributes, \ + _typedArray::obj_setGenericAttributes, \ + _typedArray::obj_setPropertyAttributes, \ _typedArray::obj_setElementAttributes, \ _typedArray::obj_setSpecialAttributes, \ - _typedArray::obj_deleteProperty, \ + _typedArray::obj_deleteGeneric, \ _typedArray::obj_deleteProperty, \ _typedArray::obj_deleteElement, \ _typedArray::obj_deleteSpecial, \ @@ -2193,11 +2258,11 @@ InitTypedArrayClass(JSContext *cx, GlobalObject *global) if (!LinkConstructorAndPrototype(cx, ctor, proto)) return NULL; - if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.BYTES_PER_ELEMENTAtom), + if (!ctor->defineProperty(cx, cx->runtime->atomState.BYTES_PER_ELEMENTAtom, Int32Value(ArrayType::BYTES_PER_ELEMENT), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY) || - !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.BYTES_PER_ELEMENTAtom), + !proto->defineProperty(cx, cx->runtime->atomState.BYTES_PER_ELEMENTAtom, Int32Value(ArrayType::BYTES_PER_ELEMENT), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) diff --git a/js/src/jstypedarray.h b/js/src/jstypedarray.h index 9e0abedbe3d6..11893b16638f 100644 --- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -88,13 +88,14 @@ struct JS_FRIEND_API(ArrayBuffer) { JSProperty **propp); static JSBool - obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, + obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs); + static JSBool + obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs); - static JSBool obj_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs); - static JSBool obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs); @@ -113,38 +114,38 @@ struct JS_FRIEND_API(ArrayBuffer) { obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp); static JSBool - obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); - + obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); + static JSBool + obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); static JSBool obj_setElement(JSContext *cx, JSObject *obj, uint32 index, Value *vp, JSBool strict); - static JSBool obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict); static JSBool - obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); - + obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool + obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp); static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp); - static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp); static JSBool - obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); - + obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool + obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp); static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp); - static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp); static JSBool - obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict); - + obj_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict); + static JSBool + obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict); static JSBool obj_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict); - static JSBool obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict); @@ -222,11 +223,13 @@ struct JS_FRIEND_API(TypedArray) { static JSBool obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp); - static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp); static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp); static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp); - static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); + static JSBool obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp); static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp); static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp); diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 650eeb06ae03..d82a0d024dae 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -235,7 +235,7 @@ Wrapper::set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool Value *vp) { // FIXME (bug 596351): Need deal with strict mode. - SET(wrappedObject(wrapper)->setProperty(cx, id, vp, false)); + SET(wrappedObject(wrapper)->setGeneric(cx, id, vp, false)); } bool diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 26ed3763f9fb..77cdbf6af9d8 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -1156,8 +1156,7 @@ static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace"; static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/"; static JSObject * -ParseNodeToQName(Parser *parser, JSParseNode *pn, - JSXMLArray *inScopeNSes, JSBool isAttributeName) +ParseNodeToQName(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, JSBool isAttributeName) { JSContext *cx = parser->context; JSLinearString *uri, *prefix; @@ -1285,14 +1284,13 @@ ChompXMLWhitespace(JSContext *cx, JSString *str) } static JSXML * -ParseNodeToXML(Parser *parser, JSParseNode *pn, - JSXMLArray *inScopeNSes, uintN flags) +ParseNodeToXML(Parser *parser, ParseNode *pn, JSXMLArray *inScopeNSes, uintN flags) { JSContext *cx = parser->context; JSXML *xml, *kid, *attr, *attrj; JSLinearString *str; uint32 length, n, i, j; - JSParseNode *pn2, *pn3, *head, **pnp; + ParseNode *pn2, *pn3, *head, **pnp; JSObject *ns; JSObject *qn, *attrjqn; JSXMLClass xml_class; @@ -1771,7 +1769,7 @@ ParseXMLSource(JSContext *cx, JSString *src) return false; } - JSParseNode *pn = parser.parseXMLText(scopeChain, false); + ParseNode *pn = parser.parseXMLText(scopeChain, false); uintN flags; if (pn && GetXMLSettingFlags(cx, &flags)) { AutoNamespaceArray namespaces(cx); @@ -4594,17 +4592,15 @@ HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found) if (!prop) { xml = (JSXML *) obj->getPrivate(); if (HasSimpleContent(xml)) { - AutoObjectRooter tvr(cx); - /* * Search in String.prototype to set found whenever * GetXMLFunction returns existing function. */ - if (!js_GetClassPrototype(cx, NULL, JSProto_String, tvr.addr())) + JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx); + if (!proto) return false; - JS_ASSERT(tvr.object()); - if (!js_LookupProperty(cx, tvr.object(), funid, &pobj, &prop)) + if (!js_LookupProperty(cx, proto, funid, &pobj, &prop)) return false; } } @@ -4787,8 +4783,8 @@ xml_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, } static JSBool -xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, - PropertyOp getter, StrictPropertyOp setter, uintN attrs) +xml_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) { if (IsFunctionObject(*v) || getter || setter || (attrs & JSPROP_ENUMERATE) == 0 || @@ -4800,6 +4796,13 @@ xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, return PutProperty(cx, obj, id, false, &tmp); } +static JSBool +xml_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v, + PropertyOp getter, StrictPropertyOp setter, uintN attrs) +{ + return xml_defineGeneric(cx, obj, ATOM_TO_JSID(name), v, getter, setter, attrs); +} + static JSBool xml_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) @@ -4807,14 +4810,14 @@ xml_defineElement(JSContext *cx, JSObject *obj, uint32 index, const Value *v, jsid id; if (!IndexToId(cx, index, &id)) return false; - return xml_defineProperty(cx, obj, id, v, getter, setter, attrs); + return xml_defineGeneric(cx, obj, id, v, getter, setter, attrs); } static JSBool xml_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) { - return xml_defineProperty(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); + return xml_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs); } static JSBool @@ -4856,9 +4859,9 @@ xml_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) } static JSBool -xml_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) +xml_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict) { - return xml_setGeneric(cx, obj, id, vp, strict); + return xml_setGeneric(cx, obj, ATOM_TO_JSID(name), vp, strict); } static JSBool @@ -4877,7 +4880,7 @@ xml_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool st } static JSBool -xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +xml_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { JSBool found; if (!HasProperty(cx, obj, IdToJsval(id), &found)) @@ -4887,23 +4890,29 @@ xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return JS_TRUE; } +static JSBool +xml_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return xml_getGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + static JSBool xml_getElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return xml_getAttributes(cx, obj, id, attrsp); + return xml_getGenericAttributes(cx, obj, id, attrsp); } static JSBool xml_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return xml_getAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return xml_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } static JSBool -xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) +xml_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { JSBool found; if (!HasProperty(cx, obj, IdToJsval(id), &found)) @@ -4917,23 +4926,29 @@ xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) return true; } +static JSBool +xml_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, uintN *attrsp) +{ + return xml_setGenericAttributes(cx, obj, ATOM_TO_JSID(name), attrsp); +} + static JSBool xml_setElementAttributes(JSContext *cx, JSObject *obj, uint32 index, uintN *attrsp) { jsid id; if (!IndexToId(cx, index, &id)) return false; - return xml_setAttributes(cx, obj, id, attrsp); + return xml_setGenericAttributes(cx, obj, id, attrsp); } static JSBool xml_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, uintN *attrsp) { - return xml_setAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); + return xml_setGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp); } static JSBool -xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) +xml_deleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { JSXML *xml; jsval idval; @@ -4977,6 +4992,12 @@ xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool st return true; } +static JSBool +xml_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict) +{ + return xml_deleteGeneric(cx, obj, ATOM_TO_JSID(name), rval, strict); +} + static JSBool xml_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBool strict) { @@ -5007,7 +5028,7 @@ xml_deleteElement(JSContext *cx, JSObject *obj, uint32 index, Value *rval, JSBoo static JSBool xml_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict) { - return xml_deleteProperty(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); + return xml_deleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict); } static JSString * @@ -5312,7 +5333,7 @@ JS_FRIEND_DATA(Class) js::XMLClass = { xml_lookupProperty, xml_lookupElement, xml_lookupSpecial, - xml_defineProperty, + xml_defineGeneric, xml_defineProperty, xml_defineElement, xml_defineSpecial, @@ -5320,19 +5341,19 @@ JS_FRIEND_DATA(Class) js::XMLClass = { xml_getProperty, xml_getElement, xml_getSpecial, - xml_setProperty, + xml_setGeneric, xml_setProperty, xml_setElement, xml_setSpecial, - xml_getAttributes, - xml_getAttributes, + xml_getGenericAttributes, + xml_getPropertyAttributes, xml_getElementAttributes, xml_getSpecialAttributes, - xml_setAttributes, - xml_setAttributes, + xml_setGenericAttributes, + xml_setPropertyAttributes, xml_setElementAttributes, xml_setSpecialAttributes, - xml_deleteProperty, + xml_deleteGeneric, xml_deleteProperty, xml_deleteElement, xml_deleteSpecial, @@ -6007,7 +6028,7 @@ NamespacesToJSArray(JSContext *cx, JSXMLArray *array, jsval *rval) if (!ns) continue; tvr.set(ObjectValue(*ns)); - if (!arrayobj->setProperty(cx, INT_TO_JSID(i), tvr.addr(), false)) + if (!arrayobj->setElement(cx, i, tvr.addr(), false)) return false; } return true; @@ -7403,7 +7424,7 @@ js_InitXMLClass(JSContext *cx, JSObject *obj) JS_DefineFunction(cx, global, js_XMLList_str, XMLList, 1, JSFUN_CONSTRUCTOR); if (!xmllist) return NULL; - if (!xmllist->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), + if (!xmllist->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom, ObjectValue(*xmlProto), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { @@ -7505,8 +7526,8 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp) if (!ns) return JS_FALSE; v = OBJECT_TO_JSVAL(ns); - if (!obj->defineProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, v, - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { + if (!obj->defineSpecial(cx, SpecialId::defaultXMLNamespace(), v, + JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { return JS_FALSE; } *vp = v; @@ -7524,8 +7545,8 @@ js_SetDefaultXMLNamespace(JSContext *cx, const Value &v) return JS_FALSE; JSObject &varobj = cx->fp()->varObj(); - if (!varobj.defineProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, ObjectValue(*ns), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { + if (!varobj.defineSpecial(cx, SpecialId::defaultXMLNamespace(), ObjectValue(*ns), + JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT)) { return JS_FALSE; } return JS_TRUE; @@ -7707,7 +7728,6 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp) * chain lookup. */ JSObject *target = obj; - AutoObjectRooter tvr(cx); for (;;) { if (!js_GetProperty(cx, target, id, vp)) return false; @@ -7716,7 +7736,6 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp) target = target->getProto(); if (target == NULL || !target->isNative()) break; - tvr.setObject(target); } JSXML *xml = (JSXML *) obj->getPrivate(); @@ -7724,11 +7743,11 @@ GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp) return true; /* Search in String.prototype to implement 11.2.2.1 Step 3(f). */ - if (!js_GetClassPrototype(cx, NULL, JSProto_String, tvr.addr())) + JSObject *proto = obj->getGlobal()->getOrCreateStringPrototype(cx); + if (!proto) return false; - JS_ASSERT(tvr.object()); - return tvr.object()->getGeneric(cx, id, vp); + return proto->getGeneric(cx, id, vp); } static JSXML * diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index f9523a0cdc2b..6abcde21033c 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -1498,7 +1498,7 @@ public: ptrdiff_t nextOffset; while ((nextOffset = offset + SN_DELTA(sn)) <= relpc && !SN_IS_TERMINATOR(sn)) { offset = nextOffset; - JSSrcNoteType type = (JSSrcNoteType) SN_TYPE(sn); + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE || type == SRC_NEWLINE) { if (type == SRC_SETLINE) lineno = js_GetSrcNoteOffset(sn, 0); @@ -4710,14 +4710,9 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom) return true; } - /* - * Bake in String.prototype. This is safe because of compileAndGo. - * We must pass an explicit scope chain only because JSD calls into - * here via the recompiler with a dummy context, and we need to use - * the global object for the script we are now compiling. - */ - JSObject *obj; - if (!js_GetClassPrototype(cx, globalObj, JSProto_String, &obj)) + /* Bake in String.prototype. This is safe because of compileAndGo. */ + JSObject *obj = globalObj->getOrCreateStringPrototype(cx); + if (!obj) return false; /* @@ -5665,13 +5660,20 @@ mjit::Compiler::jsop_this() if (script->hasFunction && !script->strictModeCode) { FrameEntry *thisFe = frame.peek(-1); - /* - * We don't inline calls to scripts which use 'this' but might require - * 'this' to be wrapped. - */ - JS_ASSERT(!thisFe->isNotType(JSVAL_TYPE_OBJECT)); - if (!thisFe->isType(JSVAL_TYPE_OBJECT)) { + /* + * Watch out for an obscure case where we don't know we are pushing + * an object: the script has not yet had a 'this' value assigned, + * so no pushed 'this' type has been inferred. Don't mark the type + * as known in this case, preserving the invariant that compiler + * types reflect inferred types. + */ + if (cx->typeInferenceEnabled() && knownPushedType(0) != JSVAL_TYPE_OBJECT) { + prepareStubCall(Uses(1)); + INLINE_STUBCALL(stubs::This, REJOIN_FALLTHROUGH); + return; + } + JSValueType type = cx->typeInferenceEnabled() ? types::TypeScript::ThisTypes(script)->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN; @@ -5683,16 +5685,6 @@ mjit::Compiler::jsop_this() stubcc.rejoin(Changes(1)); } - /* - * Watch out for an obscure case where we don't know we are pushing - * an object: the script has not yet had a 'this' value assigned, - * so no pushed 'this' type has been inferred. Don't mark the type - * as known in this case, preserving the invariant that compiler - * types reflect inferred types. - */ - if (cx->typeInferenceEnabled() && knownPushedType(0) != JSVAL_TYPE_OBJECT) - return; - // Now we know that |this| is an object. frame.pop(); frame.learnThisIsObject(type != JSVAL_TYPE_OBJECT); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 0b0f6d139d3a..63aac7eb0922 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -2075,20 +2075,20 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic) if (lval.isObject()) { objv = lval; } else { - JSProtoKey protoKey; + GlobalObject *global = f.fp()->scopeChain().getGlobal(); + JSObject *pobj; if (lval.isString()) { - protoKey = JSProto_String; + pobj = global->getOrCreateStringPrototype(cx); } else if (lval.isNumber()) { - protoKey = JSProto_Number; + pobj = global->getOrCreateNumberPrototype(cx); } else if (lval.isBoolean()) { - protoKey = JSProto_Boolean; + pobj = global->getOrCreateBooleanPrototype(cx); } else { JS_ASSERT(lval.isNull() || lval.isUndefined()); js_ReportIsNullOrUndefined(cx, -1, lval, NULL); THROW(); } - JSObject *pobj; - if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj)) + if (!pobj) THROW(); objv.setObject(*pobj); } diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 51bb2bb7c72f..4f18d22b70b6 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -254,6 +254,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) JS_ASSERT(atom); } + PropertyName *name = atom->asPropertyName(); jsid id = ATOM_TO_JSID(atom); if (entry && JS_LIKELY(!obj->getOps()->setProperty)) { uintN defineHow; @@ -267,7 +268,7 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom) if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, strict)) THROW(); } else { - if (!obj->setProperty(cx, id, &rval, strict)) + if (!obj->setProperty(cx, name, &rval, strict)) THROW(); } } while (0); @@ -287,7 +288,7 @@ stubs::SetPropNoCache(VMFrame &f, JSAtom *atom) THROW(); Value rval = f.regs.sp[-1]; - if (!obj->setProperty(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1], strict)) + if (!obj->setGeneric(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1], strict)) THROW(); f.regs.sp[-2] = rval; } @@ -304,11 +305,7 @@ stubs::SetGlobalNameNoCache(VMFrame &f, JSAtom *atom) Value rval = f.regs.sp[-1]; Value &lref = f.regs.sp[-2]; JSObject *obj = ValueToObject(cx, &lref); - if (!obj) - THROW(); - jsid id = ATOM_TO_JSID(atom); - - if (!obj->setProperty(cx, id, &rval, strict)) + if (!obj || !obj->setProperty(cx, atom->asPropertyName(), &rval, strict)) THROW(); f.regs.sp[-2] = f.regs.sp[-1]; @@ -582,7 +579,7 @@ stubs::SetElem(VMFrame &f) } } } while (0); - if (!obj->setProperty(cx, id, &rval, strict)) + if (!obj->setGeneric(cx, id, &rval, strict)) THROW(); end_setelem: /* :FIXME: Moving the assigned object into the lowest stack slot @@ -798,8 +795,11 @@ stubs::DefFun(VMFrame &f, JSFunction *fun) do { /* Steps 5d, 5f. */ if (!prop || pobj != parent) { - if (!parent->defineProperty(cx, id, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) + if (!parent->defineProperty(cx, name, rval, + JS_PropertyStub, JS_StrictPropertyStub, attrs)) + { THROW(); + } break; } @@ -808,8 +808,11 @@ stubs::DefFun(VMFrame &f, JSFunction *fun) Shape *shape = reinterpret_cast(prop); if (parent->isGlobal()) { if (shape->configurable()) { - if (!parent->defineProperty(cx, id, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs)) + if (!parent->defineProperty(cx, name, rval, + JS_PropertyStub, JS_StrictPropertyStub, attrs)) + { THROW(); + } break; } @@ -831,7 +834,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun) */ /* Step 5f. */ - if (!parent->setProperty(cx, id, &rval, strict)) + if (!parent->setProperty(cx, name, &rval, strict)) THROW(); } while (false); } @@ -1370,7 +1373,7 @@ stubs::InitElem(VMFrame &f, uint32 last) if (last && !js_SetLengthProperty(cx, obj, (jsuint) (JSID_TO_INT(id) + 1))) THROW(); } else { - if (!obj->defineProperty(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) + if (!obj->defineGeneric(cx, id, rref, NULL, NULL, JSPROP_ENUMERATE)) THROW(); } } @@ -1435,14 +1438,10 @@ stubs::RegExp(VMFrame &f, JSObject *regex) { /* * Push a regexp object cloned from the regexp literal object mapped by the - * bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was - * flouted by many browser-based implementations. - * - * We avoid the GetScopeChain call here and pass fp->scopeChain() as - * js_GetClassPrototype uses the latter only to locate the global. + * bytecode at pc. */ - JSObject *proto; - if (!js_GetClassPrototype(f.cx, &f.fp()->scopeChain(), JSProto_RegExp, &proto)) + JSObject *proto = f.fp()->scopeChain().getGlobal()->getOrCreateRegExpPrototype(f.cx); + if (!proto) THROW(); JS_ASSERT(proto); JSObject *obj = js_CloneRegExpObject(f.cx, regex, proto); @@ -1635,20 +1634,20 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom) if (lval.isObject()) { objv = lval; } else { - JSProtoKey protoKey; + GlobalObject *global = f.fp()->scopeChain().getGlobal(); + JSObject *pobj; if (lval.isString()) { - protoKey = JSProto_String; + pobj = global->getOrCreateStringPrototype(cx); } else if (lval.isNumber()) { - protoKey = JSProto_Number; + pobj = global->getOrCreateNumberPrototype(cx); } else if (lval.isBoolean()) { - protoKey = JSProto_Boolean; + pobj = global->getOrCreateBooleanPrototype(cx); } else { JS_ASSERT(lval.isNull() || lval.isUndefined()); js_ReportIsNullOrUndefined(cx, -1, lval, NULL); THROW(); } - JSObject *pobj; - if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj)) + if (!pobj) THROW(); objv.setObject(*pobj); } @@ -2210,7 +2209,7 @@ stubs::DelName(VMFrame &f, JSAtom *atom) f.regs.sp++; f.regs.sp[-1] = BooleanValue(true); if (prop) { - if (!obj->deleteProperty(f.cx, id, &f.regs.sp[-1], false)) + if (!obj->deleteProperty(f.cx, atom->asPropertyName(), &f.regs.sp[-1], false)) THROW(); } } @@ -2226,7 +2225,7 @@ stubs::DelProp(VMFrame &f, JSAtom *atom) THROW(); Value rval; - if (!obj->deleteProperty(cx, ATOM_TO_JSID(atom), &rval, strict)) + if (!obj->deleteGeneric(cx, ATOM_TO_JSID(atom), &rval, strict)) THROW(); f.regs.sp[-1] = rval; @@ -2249,7 +2248,7 @@ stubs::DelElem(VMFrame &f) if (!FetchElementId(f, obj, f.regs.sp[-1], id, &f.regs.sp[-1])) THROW(); - if (!obj->deleteProperty(cx, id, &f.regs.sp[-2], strict)) + if (!obj->deleteGeneric(cx, id, &f.regs.sp[-2], strict)) THROW(); } @@ -2308,7 +2307,7 @@ stubs::SetConst(VMFrame &f, JSAtom *atom) JSObject *obj = &f.fp()->varObj(); const Value &ref = f.regs.sp[-1]; - if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), ref, + if (!obj->defineProperty(cx, atom->asPropertyName(), ref, JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) { THROW(); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index a8b8c5b5cf88..3b8d3a6c4650 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1841,27 +1841,19 @@ UpdateSwitchTableBounds(JSContext *cx, JSScript *script, uintN offset, static void SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp) { - uintN offset, lineno, delta, caseOff, switchTableStart, switchTableEnd; - jssrcnote *notes, *sn; - JSSrcNoteType type; - const char *name; - uint32 index; - JSAtom *atom; - JSString *str; - Sprint(sp, "\nSource notes:\n"); Sprint(sp, "%4s %4s %5s %6s %-8s %s\n", "ofs", "line", "pc", "delta", "desc", "args"); Sprint(sp, "---- ---- ----- ------ -------- ------\n"); - offset = 0; - lineno = script->lineno; - notes = script->notes(); - switchTableEnd = switchTableStart = 0; - for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { - delta = SN_DELTA(sn); + uintN offset = 0; + uintN lineno = script->lineno; + jssrcnote *notes = script->notes(); + uintN switchTableEnd = 0, switchTableStart = 0; + for (jssrcnote *sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) { + uintN delta = SN_DELTA(sn); offset += delta; - type = (JSSrcNoteType) SN_TYPE(sn); - name = js_SrcNoteSpec[type].name; + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); + const char *name = js_SrcNoteSpec[type].name; if (type == SRC_LABEL) { /* Check if the source note is for a switch case. */ if (switchTableStart <= offset && offset < switchTableEnd) { @@ -1901,24 +1893,23 @@ SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp) case SRC_LABEL: case SRC_LABELBRACE: case SRC_BREAK2LABEL: - case SRC_CONT2LABEL: - index = js_GetSrcNoteOffset(sn, 0); - atom = script->getAtom(index); + case SRC_CONT2LABEL: { + uint32 index = js_GetSrcNoteOffset(sn, 0); + JSAtom *atom = script->getAtom(index); Sprint(sp, " atom %u (", index); - { - size_t len = PutEscapedString(NULL, 0, atom, '\0'); - if (char *buf = SprintReserveAmount(sp, len)) { - PutEscapedString(buf, len, atom, 0); - buf[len] = '\0'; - } + size_t len = PutEscapedString(NULL, 0, atom, '\0'); + if (char *buf = SprintReserveAmount(sp, len)) { + PutEscapedString(buf, len, atom, 0); + buf[len] = '\0'; } Sprint(sp, ")"); break; + } case SRC_FUNCDEF: { - index = js_GetSrcNoteOffset(sn, 0); + uint32 index = js_GetSrcNoteOffset(sn, 0); JSObject *obj = script->getObject(index); JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj); - str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT); + JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT); JSAutoByteString bytes; if (!str || !bytes.encode(cx, str)) ReportException(cx); @@ -1930,7 +1921,7 @@ SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp) if (op == JSOP_GOTO || op == JSOP_GOTOX) break; Sprint(sp, " length %u", uintN(js_GetSrcNoteOffset(sn, 0))); - caseOff = (uintN) js_GetSrcNoteOffset(sn, 1); + uintN caseOff = (uintN) js_GetSrcNoteOffset(sn, 1); if (caseOff) Sprint(sp, " first case offset %u", caseOff); UpdateSwitchTableBounds(cx, script, offset, @@ -3166,7 +3157,7 @@ CopyProperty(JSContext *cx, JSObject *obj, JSObject *referent, jsid id, if (*objp != referent) return true; if (!referent->getGeneric(cx, id, &desc.value) || - !referent->getAttributes(cx, id, &desc.attrs)) { + !referent->getGenericAttributes(cx, id, &desc.attrs)) { return false; } desc.attrs &= JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; @@ -4626,42 +4617,6 @@ static JSPropertySpec its_props[] = { {NULL,0,0,NULL,NULL} }; -#ifdef JSD_LOWLEVEL_SOURCE -/* - * This facilitates sending source to JSD (the debugger system) in the shell - * where the source is loaded using the JSFILE hack in jsscan. The function - * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook. - * A more normal embedding (e.g. mozilla) loads source itself and can send - * source directly to JSD without using this hook scheme. - */ -static void -SendSourceToJSDebugger(const char *filename, uintN lineno, - jschar *str, size_t length, - void **listenerTSData, JSDContext* jsdc) -{ - JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData; - - if (!jsdsrc) { - if (!filename) - filename = "typein"; - if (1 == lineno) { - jsdsrc = JSD_NewSourceText(jsdc, filename); - } else { - jsdsrc = JSD_FindSourceForURL(jsdc, filename); - if (jsdsrc && JSD_SOURCE_PARTIAL != - JSD_GetSourceStatus(jsdc, jsdsrc)) { - jsdsrc = NULL; - } - } - } - if (jsdsrc) { - jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length, - JSD_SOURCE_PARTIAL); - } - *listenerTSData = jsdsrc; -} -#endif /* JSD_LOWLEVEL_SOURCE */ - static JSBool its_noisy; /* whether to be noisy when finalizing it */ static JSBool its_enum_fail;/* whether to fail when enumerating it */ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index b3d57fb6524c..06bf0c7de292 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2027,7 +2027,7 @@ class BytecodeRangeWithLineNumbers : private BytecodeRange * and including the current offset. */ while (!SN_IS_TERMINATOR(sn) && snpc <= frontPC()) { - JSSrcNoteType type = (JSSrcNoteType) SN_TYPE(sn); + SrcNoteType type = (SrcNoteType) SN_TYPE(sn); if (type == SRC_SETLINE) lineno = size_t(js_GetSrcNoteOffset(sn, 0)); else if (type == SRC_NEWLINE) @@ -2186,7 +2186,7 @@ DebuggerScript_getAllOffsets(JSContext *cx, uintN argc, Value *vp) offsets = NewDenseEmptyArray(cx); if (!offsets || !ValueToId(cx, NumberValue(lineno), &id) || - !result->defineProperty(cx, id, ObjectValue(*offsets))) + !result->defineGeneric(cx, id, ObjectValue(*offsets))) { return false; } @@ -2742,11 +2742,12 @@ EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *ch * we use a static level that will cause us not to attempt to optimize * variable references made by this frame. */ - JSScript *script = Compiler::compileScript(cx, scobj, fp, fp->scopeChain().principals(cx), - TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT, - chars, length, - filename, lineno, cx->findVersion(), - NULL, UpvarCookie::UPVAR_LEVEL_LIMIT); + JSScript *script = BytecodeCompiler::compileScript(cx, scobj, fp, + fp->scopeChain().principals(cx), + TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT, + chars, length, filename, lineno, + cx->findVersion(), NULL, + UpvarCookie::UPVAR_LEVEL_LIMIT); if (!script) return false; @@ -3290,7 +3291,7 @@ DebuggerObject_deleteProperty(JSContext *cx, uintN argc, Value *vp) return false; ErrorCopier ec(ac, dbg->toJSObject()); - return obj->deleteProperty(cx, id, &args.rval(), false); + return obj->deleteGeneric(cx, id, &args.rval(), false); } enum SealHelperOp { Seal, Freeze, PreventExtensions }; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index ca801218e20b..ad7ca3ac9b71 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -58,13 +58,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj) { JS_ASSERT(obj->isNative()); - GlobalObject *global = obj->asGlobal(); - if (!global->functionObjectClassesInitialized()) { - if (!global->initFunctionAndObjectClasses(cx)) - return NULL; - } - - return global->getObjectPrototype(); + return obj->asGlobal()->getOrCreateObjectPrototype(cx); } JSObject * @@ -72,10 +66,7 @@ js_InitFunctionClass(JSContext *cx, JSObject *obj) { JS_ASSERT(obj->isNative()); - GlobalObject *global = obj->asGlobal(); - return global->functionObjectClassesInitialized() - ? global->getFunctionPrototype() - : global->initFunctionAndObjectClasses(cx); + return obj->asGlobal()->getOrCreateFunctionPrototype(cx); } static JSBool @@ -282,7 +273,7 @@ GlobalObject::initStandardClasses(JSContext *cx) JSAtomState &state = cx->runtime->atomState; /* Define a top-level property 'undefined' with the undefined value. */ - if (!defineProperty(cx, ATOM_TO_JSID(state.typeAtoms[JSTYPE_VOID]), UndefinedValue(), + if (!defineProperty(cx, state.typeAtoms[JSTYPE_VOID], UndefinedValue(), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY)) { return false; @@ -400,8 +391,8 @@ CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &glo JSObject * GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp) { - JSObject *objectProto; - if (!js_GetClassPrototype(cx, this, JSProto_Object, &objectProto)) + JSObject *objectProto = getOrCreateObjectPrototype(cx); + if (!objectProto) return NULL; return CreateBlankProto(cx, clasp, *objectProto, *this); @@ -416,10 +407,10 @@ GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObje bool LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto) { - return ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), + return ctor->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom, ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY) && - proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), + proto->defineProperty(cx, cx->runtime->atomState.constructorAtom, ObjectValue(*ctor), JS_PropertyStub, JS_StrictPropertyStub, 0); } diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index e89496073d83..9c4aa9d8cab5 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -41,11 +41,17 @@ #ifndef GlobalObject_h___ #define GlobalObject_h___ +#include "jsarray.h" +#include "jsbool.h" #include "jsfun.h" #include "jsiter.h" +#include "jsnum.h" +#include "jstypedarray.h" #include "js/Vector.h" +#include "builtin/RegExp.h" + extern JSObject * js_InitObjectClass(JSContext *cx, JSObject *obj); @@ -159,6 +165,48 @@ class GlobalObject : public ::JSObject { v.setObject(*evalobj); } + Value getConstructor(JSProtoKey key) const { + JS_ASSERT(key <= JSProto_LIMIT); + return getSlot(key); + } + + Value getPrototype(JSProtoKey key) const { + JS_ASSERT(key <= JSProto_LIMIT); + return getSlot(JSProto_LIMIT + key); + } + + bool classIsInitialized(JSProtoKey key) const { + bool inited = !getConstructor(key).isUndefined(); + JS_ASSERT(inited == !getPrototype(key).isUndefined()); + return inited; + } + + bool functionObjectClassesInitialized() const { + bool inited = classIsInitialized(JSProto_Function); + JS_ASSERT(inited == classIsInitialized(JSProto_Object)); + return inited; + } + + bool arrayClassInitialized() const { + return classIsInitialized(JSProto_Array); + } + + bool booleanClassInitialized() const { + return classIsInitialized(JSProto_Boolean); + } + bool numberClassInitialized() const { + return classIsInitialized(JSProto_Number); + } + bool stringClassInitialized() const { + return classIsInitialized(JSProto_String); + } + bool regexpClassInitialized() const { + return classIsInitialized(JSProto_RegExp); + } + bool arrayBufferClassInitialized() const { + return classIsInitialized(JSProto_ArrayBuffer); + } + public: static GlobalObject *create(JSContext *cx, Class *clasp); @@ -185,27 +233,68 @@ class GlobalObject : public ::JSObject { */ JSObject *createBlankPrototypeInheriting(JSContext *cx, js::Class *clasp, JSObject &proto); - bool functionObjectClassesInitialized() const { - bool inited = !getSlot(JSProto_Function).isUndefined(); - JS_ASSERT(inited == !getSlot(JSProto_LIMIT + JSProto_Function).isUndefined()); - JS_ASSERT(inited == !getSlot(JSProto_Object).isUndefined()); - JS_ASSERT(inited == !getSlot(JSProto_LIMIT + JSProto_Object).isUndefined()); - return inited; + JSObject *getOrCreateObjectPrototype(JSContext *cx) { + if (!functionObjectClassesInitialized()) { + if (!initFunctionAndObjectClasses(cx)) + return NULL; + } + return &getPrototype(JSProto_Object).toObject(); } - JSObject *getFunctionPrototype() const { - JS_ASSERT(functionObjectClassesInitialized()); - return &getSlot(JSProto_LIMIT + JSProto_Function).toObject(); + JSObject *getOrCreateFunctionPrototype(JSContext *cx) { + if (!functionObjectClassesInitialized()) { + if (!initFunctionAndObjectClasses(cx)) + return NULL; + } + return &getPrototype(JSProto_Function).toObject(); } - JSObject *getObjectPrototype() const { - JS_ASSERT(functionObjectClassesInitialized()); - return &getSlot(JSProto_LIMIT + JSProto_Object).toObject(); + JSObject *getOrCreateArrayPrototype(JSContext *cx) { + if (!arrayClassInitialized()) { + if (!js_InitArrayClass(cx, this)) + return NULL; + } + return &getPrototype(JSProto_Array).toObject(); } - JSObject *getThrowTypeError() const { - JS_ASSERT(functionObjectClassesInitialized()); - return &getSlot(THROWTYPEERROR).toObject(); + JSObject *getOrCreateBooleanPrototype(JSContext *cx) { + if (!booleanClassInitialized()) { + if (!js_InitBooleanClass(cx, this)) + return NULL; + } + return &getPrototype(JSProto_Boolean).toObject(); + } + + JSObject *getOrCreateNumberPrototype(JSContext *cx) { + if (!numberClassInitialized()) { + if (!js_InitNumberClass(cx, this)) + return NULL; + } + return &getPrototype(JSProto_Number).toObject(); + } + + JSObject *getOrCreateStringPrototype(JSContext *cx) { + if (!stringClassInitialized()) { + if (!js_InitStringClass(cx, this)) + return NULL; + } + return &getPrototype(JSProto_String).toObject(); + } + + JSObject *getOrCreateRegExpPrototype(JSContext *cx) { + if (!regexpClassInitialized()) { + if (!js_InitRegExpClass(cx, this)) + return NULL; + } + return &getPrototype(JSProto_RegExp).toObject(); + } + + JSObject *getOrCreateArrayBufferPrototype(JSContext *cx) { + if (!arrayBufferClassInitialized()) { + if (!js_InitTypedArrayClasses(cx, this)) + return NULL; + } + return &getPrototype(JSProto_ArrayBuffer).toObject(); } JSObject *getOrCreateGeneratorPrototype(JSContext *cx) { @@ -216,6 +305,11 @@ class GlobalObject : public ::JSObject { return &v.toObject(); } + JSObject *getThrowTypeError() const { + JS_ASSERT(functionObjectClassesInitialized()); + return &getSlot(THROWTYPEERROR).toObject(); + } + RegExpStatics *getRegExpStatics() const { JSObject &resObj = getSlot(REGEXP_STATICS).toObject(); return static_cast(resObj.getPrivate()); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 4715445d46b3..9a491fb01c4d 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -7608,6 +7608,11 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString, textFrame = static_cast(textFrame->GetNextContinuation())) { // For each text frame continuation in this block ... + if (textFrame->GetStateBits() & NS_FRAME_IS_DIRTY) { + // We don't trust dirty frames, expecially when computing rendered text. + break; + } + // Ensure the text run and grab the gfxSkipCharsIterator for it gfxSkipCharsIterator iter = textFrame->EnsureTextRun(); if (!textFrame->mTextRun) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index f3cca27f623e..c776d7091114 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -264,7 +264,7 @@ public: bool ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURL, // for error reporting PRUint32 aLineNumber, // for error reporting - nsTArray& aSelectorList); + InfallibleTArray& aSelectorList); protected: class nsAutoParseCompoundProperty; @@ -331,7 +331,7 @@ protected: bool SkipAtRule(bool aInsideBlock); bool SkipDeclaration(bool aCheckForBraces); - bool PushGroup(css::GroupRule* aRule); + void PushGroup(css::GroupRule* aRule); void PopGroup(); bool ParseRuleSet(RuleAppendFunc aAppendFunc, void* aProcessData, @@ -366,7 +366,7 @@ protected: bool ParsePageRule(RuleAppendFunc aAppendFunc, void* aProcessData); bool ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aProcessData); already_AddRefed ParseKeyframeRule(); - bool ParseKeyframeSelectorList(nsTArray& aSelectorList); + bool ParseKeyframeSelectorList(InfallibleTArray& aSelectorList); enum nsSelectorParsingStatus { // we have parsed a selector and we saw a token that cannot be @@ -505,7 +505,7 @@ protected: bool ParseOneFamily(nsAString& aValue); bool ParseFamily(nsCSSValue& aValue); bool ParseFontSrc(nsCSSValue& aValue); - bool ParseFontSrcFormat(nsTArray& values); + bool ParseFontSrcFormat(InfallibleTArray& values); bool ParseFontRanges(nsCSSValue& aValue); bool ParseListStyle(); bool ParseMargin(); @@ -601,7 +601,7 @@ protected: bool ParseFunctionInternals(const PRInt32 aVariantMask[], PRUint16 aMinElems, PRUint16 aMaxElems, - nsTArray& aOutput); + InfallibleTArray& aOutput); /* Functions for -moz-transform-origin/-moz-perspective-origin Parsing */ bool ParseMozTransformOrigin(bool aPerspective); @@ -677,7 +677,7 @@ protected: #endif // Stack of rule groups; used for @media and such. - nsTArray > mGroupStack; + InfallibleTArray > mGroupStack; // During the parsing of a property (which may be a shorthand), the data // are stored in |mTempData|. (It is needed to ensure that parser @@ -831,8 +831,7 @@ CSSParserImpl::InitScanner(const nsSubstring& aString, nsIURI* aSheetURI, // the stream until we're done parsing. NS_ASSERTION(! mScannerInited, "already have scanner"); - mScanner.Init(nsnull, aString.BeginReading(), aString.Length(), aSheetURI, - aLineNumber, mSheet, mChildLoader); + mScanner.Init(aString, aSheetURI, aLineNumber, mSheet, mChildLoader); #ifdef DEBUG mScannerInited = true; @@ -1017,17 +1016,11 @@ CSSParserImpl::ParseDeclarations(const nsAString& aBuffer, // We could check if it was already empty, but... *aChanged = true; - nsresult rv = NS_OK; for (;;) { // If we cleared the old decl, then we want to be calling // ValueAppended as we parse. if (!ParseDeclaration(aDeclaration, false, true, aChanged)) { - rv = mScanner.GetLowLevelError(); - if (NS_FAILED(rv)) - break; - if (!SkipDeclaration(false)) { - rv = mScanner.GetLowLevelError(); break; } } @@ -1035,7 +1028,7 @@ CSSParserImpl::ParseDeclarations(const nsAString& aBuffer, aDeclaration->CompressFrom(&mData); ReleaseScanner(); - return rv; + return NS_OK; } nsresult @@ -1144,9 +1137,8 @@ CSSParserImpl::ParseProperty(const nsCSSProperty aPropID, mTempData.AssertInitialState(); - nsresult result = mScanner.GetLowLevelError(); ReleaseScanner(); - return result; + return NS_OK; } nsresult @@ -1180,14 +1172,13 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer, // to a media query. (The main substative difference is the relative // precedence of commas and paretheses.) - GatherMedia(aMediaList, false); // can only fail on low-level error (OOM) + GatherMedia(aMediaList, false); - nsresult rv = mScanner.GetLowLevelError(); CLEAR_ERROR(); ReleaseScanner(); mHTMLMediaMode = false; - return rv; + return NS_OK; } nsresult @@ -1202,40 +1193,46 @@ CSSParserImpl::ParseColorString(const nsSubstring& aBuffer, nsCSSValue value; // Parse a color, and check that there's nothing else after it. bool colorParsed = ParseColor(value) && !GetToken(true); - nsresult rv = mScanner.GetLowLevelError(); OUTPUT_ERROR(); ReleaseScanner(); if (!colorParsed) { - return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE; + return NS_ERROR_FAILURE; } - if (value.GetUnit() == eCSSUnit_Ident) { + switch (value.GetUnit()) { + case eCSSUnit_Color: + *aColor = value.GetColorValue(); + return NS_OK; + + case eCSSUnit_Ident: { + nsDependentString id(value.GetStringBufferValue()); + if (!NS_ColorNameToRGB(id, aColor)) { + return NS_ERROR_FAILURE; + } + return NS_OK; + } + + case eCSSUnit_EnumColor: { + PRInt32 val = value.GetIntValue(); + if (val < 0) { + // XXX - negative numbers are NS_COLOR_CURRENTCOLOR, + // NS_COLOR_MOZ_HYPERLINKTEXT, etc. which we don't handle. + // Should remove this limitation at some point. + return NS_ERROR_FAILURE; + } nscolor rgba; - if (NS_ColorNameToRGB(nsDependentString(value.GetStringBufferValue()), &rgba)) { - (*aColor) = rgba; - rv = NS_OK; - } - } else if (value.GetUnit() == eCSSUnit_Color) { - (*aColor) = value.GetColorValue(); - rv = NS_OK; - } else if (value.GetUnit() == eCSSUnit_EnumColor) { - PRInt32 intValue = value.GetIntValue(); - if (intValue >= 0) { - nscolor rgba; - rv = LookAndFeel::GetColor((LookAndFeel::ColorID) value.GetIntValue(), - &rgba); - if (NS_SUCCEEDED(rv)) - (*aColor) = rgba; - } else { - // XXX - this is NS_COLOR_CURRENTCOLOR, NS_COLOR_MOZ_HYPERLINKTEXT, etc. - // which we don't handle as per the ParseColorString definition. Should - // remove this limitation at some point. - rv = NS_ERROR_FAILURE; + nsresult rv = LookAndFeel::GetColor(LookAndFeel::ColorID(val), &rgba); + if (NS_FAILED(rv)) { + return rv; } + *aColor = rgba; + return NS_OK; } - return rv; + default: + return NS_ERROR_FAILURE; + } } nsresult @@ -1304,7 +1301,7 @@ bool CSSParserImpl::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, // for error reporting PRUint32 aLineNumber, // for error reporting - nsTArray& aSelectorList) + InfallibleTArray& aSelectorList) { NS_ABORT_IF_FALSE(aSelectorList.IsEmpty(), "given list should start empty"); @@ -1654,10 +1651,6 @@ CSSParserImpl::ParseMediaQuery(bool aInAtRule, nsMediaQuery* query = new nsMediaQuery; *aQuery = query; - if (!query) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } if (ExpectSymbol('(', true)) { // we got an expression without a media type @@ -1685,6 +1678,9 @@ CSSParserImpl::ParseMediaQuery(bool aInAtRule, // case insensitive from CSS - must be lower cased nsContentUtils::ASCIIToLower(mToken.mIdent); mediaType = do_GetAtom(mToken.mIdent); + if (!mediaType) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } if (gotNotOrOnly || (mediaType != nsGkAtoms::_not && mediaType != nsGkAtoms::only)) break; @@ -1746,9 +1742,6 @@ CSSParserImpl::GatherMedia(nsMediaList* aMedia, &hitStop)) { NS_ASSERTION(!hitStop, "should return true when hit stop"); OUTPUT_ERROR(); - if (NS_FAILED(mScanner.GetLowLevelError())) { - return false; - } if (query) { query->SetHadUnknownExpression(); } @@ -1767,11 +1760,7 @@ CSSParserImpl::GatherMedia(nsMediaList* aMedia, } } if (query) { - nsresult rv = aMedia->AppendQuery(query); - if (NS_FAILED(rv)) { - mScanner.SetLowLevelError(rv); - return false; - } + aMedia->AppendQuery(query); } if (hitStop) { break; @@ -1799,11 +1788,6 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) } nsMediaExpression *expr = aQuery->NewExpression(); - if (!expr) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - SkipUntil(')'); - return false; - } // case insensitive from CSS - must be lower cased nsContentUtils::ASCIIToLower(mToken.mIdent); @@ -1820,6 +1804,9 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery) } nsCOMPtr mediaFeatureAtom = do_GetAtom(featureString); + if (!mediaFeatureAtom) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } const nsMediaFeature *feature = nsMediaFeatures::features; for (; feature->mName; ++feature) { if (*(feature->mName) == mediaFeatureAtom) { @@ -1928,10 +1915,6 @@ bool CSSParserImpl::ParseImportRule(RuleAppendFunc aAppendFunc, void* aData) { nsRefPtr media = new nsMediaList(); - if (!media) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } nsAutoString url; if (!ParseURLOrString(url)) { @@ -2000,10 +1983,7 @@ CSSParserImpl::ParseGroupRule(css::GroupRule* aRule, } // push rule on stack, loop over children - if (!PushGroup(aRule)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + PushGroup(aRule); nsCSSSection holdSection = mSection; mSection = eCSSSection_General; @@ -2164,6 +2144,9 @@ CSSParserImpl::ProcessNameSpace(const nsString& aPrefix, if (!aPrefix.IsEmpty()) { prefix = do_GetAtom(aPrefix); + if (!prefix) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } } nsRefPtr rule = new css::NameSpaceRule(prefix, aURLSpec); @@ -2187,10 +2170,6 @@ CSSParserImpl::ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aData) } nsRefPtr rule(new nsCSSFontFaceRule()); - if (!rule) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } for (;;) { if (!GetToken(true)) { @@ -2327,7 +2306,7 @@ CSSParserImpl::ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aData) already_AddRefed CSSParserImpl::ParseKeyframeRule() { - nsTArray selectorList; + InfallibleTArray selectorList; if (!ParseKeyframeSelectorList(selectorList)) { REPORT_UNEXPECTED(PEBadSelectorKeyframeRuleIgnored); return nsnull; @@ -2347,7 +2326,7 @@ CSSParserImpl::ParseKeyframeRule() } bool -CSSParserImpl::ParseKeyframeSelectorList(nsTArray& aSelectorList) +CSSParserImpl::ParseKeyframeSelectorList(InfallibleTArray& aSelectorList) { for (;;) { if (!GetToken(true)) { @@ -2510,16 +2489,13 @@ CSSParserImpl::SkipRuleSet(bool aInsideBraces) eCSSToken_Bad_URL == tk->mType) { SkipUntil(')'); } - } + } } -bool +void CSSParserImpl::PushGroup(css::GroupRule* aRule) { - if (mGroupStack.AppendElement(aRule)) - return true; - - return false; + mGroupStack.AppendElement(aRule); } void @@ -3124,8 +3100,7 @@ CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask, nsContentUtils::ASCIIToLower(buffer); nsCOMPtr pseudo = do_GetAtom(buffer); if (!pseudo) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return eSelectorParsingStatus_Error; + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); } // stash away some info about this pseudo so we only have to get it once. @@ -3335,10 +3310,6 @@ CSSParserImpl::ParseNegatedSimpleSelector(PRInt32& aDataMask, // thing we need to change to support that is this parsing code and the // serialization code for nsCSSSelector. nsCSSSelector *newSel = new nsCSSSelector(); - if (!newSel) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return eSelectorParsingStatus_Error; - } nsCSSSelector* negations = &aSelector; while (negations->mNegations) { negations = negations->mNegations; @@ -4828,19 +4799,10 @@ CSSParserImpl::SetValueToURL(nsCSSValue& aValue, const nsString& aURL) } nsRefPtr buffer(nsCSSValue::BufferFromString(aURL)); - if (NS_UNLIKELY(!buffer)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } // Note: urlVal retains its own reference to |buffer|. nsCSSValue::URL *urlVal = new nsCSSValue::URL(buffer, mBaseURI, mSheetURI, mSheetPrincipal); - - if (NS_UNLIKELY(!urlVal)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } aValue.SetURLValue(urlVal); return true; } @@ -4858,10 +4820,6 @@ CSSParserImpl::ParseImageRect(nsCSSValue& aImage) static const PRUint32 kNumArgs = 5; nsCSSValue::Array* func = newFunction.InitFunction(eCSSKeyword__moz_image_rect, kNumArgs); - if (!func) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - break; - } // func->Item(0) is reserved for the function name. nsCSSValue& url = func->Item(1); @@ -4929,11 +4887,6 @@ bool CSSParserImpl::ParseColorStop(nsCSSValueGradient* aGradient) { nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement(); - if (!stop) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } - if (!ParseVariant(stop->mColor, VARIANT_COLOR, nsnull)) { return false; } @@ -7212,18 +7165,15 @@ bool CSSParserImpl::ParseFunctionInternals(const PRInt32 aVariantMask[], PRUint16 aMinElems, PRUint16 aMaxElems, - nsTArray &aOutput) + InfallibleTArray &aOutput) { for (PRUint16 index = 0; index < aMaxElems; ++index) { nsCSSValue newValue; if (!ParseVariant(newValue, aVariantMask[index], nsnull)) return false; - if (!aOutput.AppendElement(newValue)) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } - + aOutput.AppendElement(newValue); + // See whether to continue or whether to look for end of function. if (!ExpectSymbol(',', true)) { // We need to read the closing parenthesis, and also must take care @@ -7261,7 +7211,7 @@ CSSParserImpl::ParseFunction(const nsString &aFunction, PRUint16 aMinElems, PRUint16 aMaxElems, nsCSSValue &aValue) { - typedef nsTArray::size_type arrlen_t; + typedef InfallibleTArray::size_type arrlen_t; /* 2^16 - 2, so that if we have 2^16 - 2 transforms, we have 2^16 - 1 * elements stored in the the nsCSSValue::Array. @@ -7274,15 +7224,15 @@ CSSParserImpl::ParseFunction(const nsString &aFunction, */ nsString functionName(aFunction); - /* Read in a list of values as an nsTArray, failing if we can't or if + /* Read in a list of values as an array, failing if we can't or if * it's out of bounds. */ - nsTArray foundValues; + InfallibleTArray foundValues; if (!ParseFunctionInternals(aAllowedTypes, aMinElems, aMaxElems, foundValues)) return false; - - /* Now, convert this nsTArray into an nsCSSValue::Array object. + + /* Now, convert this array into an nsCSSValue::Array object. * We'll need N + 1 spots, one for the function name and the rest for the * arguments. In case the user has given us more than 2^16 - 2 arguments, * we'll truncate them at 2^16 - 2 arguments. @@ -7296,10 +7246,10 @@ CSSParserImpl::ParseFunction(const nsString &aFunction, convertedArray->Item(0).SetStringValue(functionName, eCSSUnit_Ident); for (PRUint16 index = 0; index + 1 < numElements; ++index) convertedArray->Item(index + 1) = foundValues[static_cast(index)]; - + /* Fill in the outparam value with the array. */ aValue.SetArrayValue(convertedArray, eCSSUnit_Function); - + /* Return it! */ return true; } @@ -7641,8 +7591,8 @@ CSSParserImpl::ParseFamily(nsCSSValue& aValue) bool CSSParserImpl::ParseFontSrc(nsCSSValue& aValue) { - // could we maybe turn nsCSSValue::Array into nsTArray? - nsTArray values; + // could we maybe turn nsCSSValue::Array into InfallibleTArray? + InfallibleTArray values; nsCSSValue cur; for (;;) { if (!GetToken(true)) @@ -7695,11 +7645,7 @@ CSSParserImpl::ParseFontSrc(nsCSSValue& aValue) return false; nsRefPtr srcVals - = nsCSSValue::Array::Create(mozilla::fallible_t(), values.Length()); - if (!srcVals) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + = nsCSSValue::Array::Create(values.Length()); PRUint32 i; for (i = 0; i < values.Length(); i++) @@ -7709,7 +7655,7 @@ CSSParserImpl::ParseFontSrc(nsCSSValue& aValue) } bool -CSSParserImpl::ParseFontSrcFormat(nsTArray & values) +CSSParserImpl::ParseFontSrcFormat(InfallibleTArray & values) { if (!GetToken(true)) return true; // EOF harmless here @@ -7745,7 +7691,7 @@ CSSParserImpl::ParseFontSrcFormat(nsTArray & values) bool CSSParserImpl::ParseFontRanges(nsCSSValue& aValue) { - nsTArray ranges; + InfallibleTArray ranges; for (;;) { if (!GetToken(true)) break; @@ -7782,11 +7728,7 @@ CSSParserImpl::ParseFontRanges(nsCSSValue& aValue) return false; nsRefPtr srcVals - = nsCSSValue::Array::Create(mozilla::fallible_t(), ranges.Length()); - if (!srcVals) { - mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY); - return false; - } + = nsCSSValue::Array::Create(ranges.Length()); for (PRUint32 i = 0; i < ranges.Length(); i++) srcVals->Item(i).SetIntValue(ranges[i], eCSSUnit_Integer); @@ -8711,6 +8653,9 @@ CSSParserImpl::GetNamespaceIdForPrefix(const nsString& aPrefix) if (mNameSpaceMap) { // user-specified identifiers are case-sensitive (bug 416106) nsCOMPtr prefix = do_GetAtom(aPrefix); + if (!prefix) { + NS_RUNTIMEABORT("do_GetAtom failed - out of memory?"); + } nameSpaceID = mNameSpaceMap->FindNameSpaceID(prefix); } // else no declared namespaces @@ -8991,7 +8936,7 @@ bool nsCSSParser::ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURI, PRUint32 aLineNumber, - nsTArray& aSelectorList) + InfallibleTArray& aSelectorList) { return static_cast(mImpl)-> ParseKeyframeSelectorString(aSelectorString, aURI, aLineNumber, diff --git a/layout/style/nsCSSParser.h b/layout/style/nsCSSParser.h index 248fd10aac0d..8f8446579ea3 100644 --- a/layout/style/nsCSSParser.h +++ b/layout/style/nsCSSParser.h @@ -204,7 +204,7 @@ public: bool ParseKeyframeSelectorString(const nsSubstring& aSelectorString, nsIURI* aURL, PRUint32 aLineNumber, - nsTArray& aSelectorList); + InfallibleTArray& aSelectorList); protected: // This is a CSSParserImpl*, but if we expose that type name in this diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 127950bc895b..e0331801887e 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1851,7 +1851,7 @@ nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) { nsCSSParser parser; - nsTArray newSelectors; + InfallibleTArray newSelectors; // FIXME: pass filename and line number if (parser.ParseKeyframeSelectorString(aKeyText, nsnull, 0, newSelectors)) { newSelectors.SwapElements(mKeys); @@ -2033,7 +2033,7 @@ nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey) { nsCSSParser parser; - nsTArray keys; + InfallibleTArray keys; // FIXME: pass filename and line number if (parser.ParseKeyframeSelectorString(aKey, nsnull, 0, keys)) { // The spec isn't clear, but we'll match on the key list, which diff --git a/layout/style/nsCSSScanner.cpp b/layout/style/nsCSSScanner.cpp index a21670c38a35..89d0edc18106 100644 --- a/layout/style/nsCSSScanner.cpp +++ b/layout/style/nsCSSScanner.cpp @@ -37,18 +37,15 @@ * * ***** END LICENSE BLOCK ***** */ -#include - -#include "mozilla/Util.h" /* tokenization of CSS style sheets */ +#include // must be first due to symbol conflicts + #include "nsCSSScanner.h" -#include "nsIFactory.h" -#include "nsIInputStream.h" -#include "nsIUnicharInputStream.h" #include "nsString.h" #include "nsCRT.h" +#include "mozilla/Util.h" // for #ifdef CSS_REPORT_PARSE_ERRORS #include "nsCOMPtr.h" @@ -74,12 +71,6 @@ static nsIFactory *gScriptErrorFactory; static nsIStringBundle *gStringBundle; #endif -// Don't bother collecting whitespace characters in token's mIdent buffer -#undef COLLECT_WHITESPACE - -// Table of character classes -static const PRUnichar CSS_ESCAPE = PRUnichar('\\'); - static const PRUint8 IS_HEX_DIGIT = 0x01; static const PRUint8 START_IDENT = 0x02; static const PRUint8 IS_IDENT = 0x04; @@ -234,7 +225,7 @@ nsCSSToken::AppendToString(nsString& aBuffer) case eCSSToken_Percentage: NS_ASSERTION(!mIntegerValid, "How did a percentage token get this set?"); aBuffer.AppendFloat(mNumber * 100.0f); - aBuffer.Append(PRUnichar('%')); // STRING USE WARNING: technically, this should be |AppendWithConversion| + aBuffer.Append(PRUnichar('%')); break; case eCSSToken_Dimension: if (mIntegerValid) { @@ -282,9 +273,7 @@ nsCSSToken::AppendToString(nsString& aBuffer) } nsCSSScanner::nsCSSScanner() - : mInputStream(nsnull) - , mReadPointer(nsnull) - , mLowLevelError(NS_OK) + : mReadPointer(nsnull) , mSVGMode(false) #ifdef CSS_REPORT_PARSE_ERRORS , mError(mErrorBuf, ArrayLength(mErrorBuf), 0) @@ -311,20 +300,6 @@ nsCSSScanner::~nsCSSScanner() } } -nsresult -nsCSSScanner::GetLowLevelError() -{ - return mLowLevelError; -} - -void -nsCSSScanner::SetLowLevelError(nsresult aErrorCode) -{ - NS_ASSERTION(aErrorCode != NS_OK, "SetLowLevelError() used to clear error"); - NS_ASSERTION(mLowLevelError == NS_OK, "there is already a low-level error"); - mLowLevelError = aErrorCode; -} - #ifdef CSS_REPORT_PARSE_ERRORS #define CSS_ERRORS_PREF "layout.css.report_errors" @@ -369,28 +344,14 @@ nsCSSScanner::ReleaseGlobals() } void -nsCSSScanner::Init(nsIUnicharInputStream* aInput, - const PRUnichar * aBuffer, PRUint32 aCount, +nsCSSScanner::Init(const nsAString& aBuffer, nsIURI* aURI, PRUint32 aLineNumber, nsCSSStyleSheet* aSheet, mozilla::css::Loader* aLoader) { - NS_PRECONDITION(!mInputStream, "Should not have an existing input stream!"); NS_PRECONDITION(!mReadPointer, "Should not have an existing input buffer!"); - // Read from stream via my own buffer - if (aInput) { - NS_PRECONDITION(!aBuffer, "Shouldn't have both input and buffer!"); - NS_PRECONDITION(aCount == 0, "Shouldn't have count with a stream"); - mInputStream = aInput; - mReadPointer = mBuffer; - mCount = 0; - } else { - NS_PRECONDITION(aBuffer, "Either aInput or aBuffer must be set"); - // Read directly from the provided buffer - mInputStream = nsnull; - mReadPointer = aBuffer; - mCount = aCount; - } + mReadPointer = aBuffer.BeginReading(); + mCount = aBuffer.Length(); #ifdef CSS_REPORT_PARSE_ERRORS // If aURI is the same as mURI, no need to reget mFileName -- it @@ -409,7 +370,6 @@ nsCSSScanner::Init(nsIUnicharInputStream* aInput, // Reset variables that we use to keep track of our progress through the input mOffset = 0; mPushbackCount = 0; - mLowLevelError = NS_OK; #ifdef CSS_REPORT_PARSE_ERRORS mColNumber = 0; @@ -618,7 +578,6 @@ nsCSSScanner::ReportUnexpectedTokenParams(nsCSSToken& tok, void nsCSSScanner::Close() { - mInputStream = nsnull; mReadPointer = nsnull; // Clean things up so we don't hold on to memory if our parser gets recycled. @@ -638,31 +597,6 @@ nsCSSScanner::Close() } } -#ifdef CSS_REPORT_PARSE_ERRORS -#define TAB_STOP_WIDTH 8 -#endif - -bool -nsCSSScanner::EnsureData() -{ - if (mOffset < mCount) - return true; - - if (!mInputStream) - return false; - - mOffset = 0; - nsresult rv = mInputStream->Read(mBuffer, CSS_BUFFER_SIZE, &mCount); - - if (NS_FAILED(rv)) { - mCount = 0; - SetLowLevelError(rv); - return false; - } - - return mCount > 0; -} - // Returns -1 on error or eof PRInt32 nsCSSScanner::Read() @@ -671,14 +605,14 @@ nsCSSScanner::Read() if (0 < mPushbackCount) { rv = PRInt32(mPushback[--mPushbackCount]); } else { - if (mOffset == mCount && !EnsureData()) { + if (mOffset == mCount) { return -1; } rv = PRInt32(mReadPointer[mOffset++]); // There are four types of newlines in CSS: "\r", "\n", "\r\n", and "\f". // To simplify dealing with newlines, they are all normalized to "\n" here if (rv == '\r') { - if (EnsureData() && mReadPointer[mOffset] == '\n') { + if (mOffset < mCount && mReadPointer[mOffset] == '\n') { mOffset++; } rv = '\n'; @@ -691,18 +625,11 @@ nsCSSScanner::Read() ++mLineNumber; #ifdef CSS_REPORT_PARSE_ERRORS mColNumber = 0; -#endif - } -#ifdef CSS_REPORT_PARSE_ERRORS - else if (rv == '\t') { - mColNumber = ((mColNumber - 1 + TAB_STOP_WIDTH) / TAB_STOP_WIDTH) - * TAB_STOP_WIDTH; - } else if (rv != '\n') { + } else { mColNumber++; - } #endif + } } -//printf("Read => %x\n", rv); return rv; } @@ -717,7 +644,6 @@ nsCSSScanner::Peek() mPushback[0] = PRUnichar(ch); mPushbackCount++; } -//printf("Peek => %x\n", mLookAhead); return PRInt32(mPushback[mPushbackCount - 1]); } @@ -848,17 +774,8 @@ nsCSSScanner::Next(nsCSSToken& aToken) if (ch == '/' && !IsSVGMode()) { PRInt32 nextChar = Peek(); if (nextChar == '*') { - (void) Read(); -#if 0 - // If we change our storage data structures such that comments are - // stored (for Editor), we should reenable this code, condition it - // on being in editor mode, and apply glazou's patch from bug - // 60290. - aToken.mIdent.SetCapacity(2); - aToken.mIdent.Assign(PRUnichar(ch)); - aToken.mIdent.Append(PRUnichar(nextChar)); - return ParseCComment(aToken); -#endif + Read(); + // FIXME: Editor wants comments to be preserved (bug 60290). if (!SkipCComment()) { return false; } @@ -977,7 +894,7 @@ nsCSSScanner::NextURL(nsCSSToken& aToken) for (;;) { ch = Read(); if (ch < 0) break; - if (ch == CSS_ESCAPE) { + if (ch == '\\') { if (!ParseAndAppendEscape(ident, false)) { ok = false; Pushback(ch); @@ -1105,7 +1022,7 @@ nsCSSScanner::ParseAndAppendEscape(nsString& aOutput, bool aInString) bool nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent) { - if (aChar == CSS_ESCAPE) { + if (aChar == '\\') { if (!ParseAndAppendEscape(aIdent, false)) { return false; } @@ -1115,7 +1032,7 @@ nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent) } for (;;) { // If nothing in pushback, first try to get as much as possible in one go - if (!mPushbackCount && EnsureData()) { + if (!mPushbackCount && mOffset < mCount) { // See how much we can consume and append in one go PRUint32 n = mOffset; // Count number of Ident characters that can be processed @@ -1134,7 +1051,7 @@ nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent) aChar = Read(); if (aChar < 0) break; - if (aChar == CSS_ESCAPE) { + if (aChar == '\\') { if (!ParseAndAppendEscape(aIdent, false)) { Pushback(aChar); break; @@ -1160,7 +1077,7 @@ nsCSSScanner::ParseRef(PRInt32 aChar, nsCSSToken& aToken) if (ch < 0) { return true; } - if (IsIdent(ch) || ch == CSS_ESCAPE) { + if (IsIdent(ch) || ch == '\\') { // First char after the '#' is a valid ident char (or an escape), // so it makes sense to keep going nsCSSTokenType type = @@ -1375,23 +1292,18 @@ nsCSSScanner::ParseString(PRInt32 aStop, nsCSSToken& aToken) aToken.mSymbol = PRUnichar(aStop); // remember how it's quoted for (;;) { // If nothing in pushback, first try to get as much as possible in one go - if (!mPushbackCount && EnsureData()) { + if (!mPushbackCount && mOffset < mCount) { // See how much we can consume and append in one go PRUint32 n = mOffset; // Count number of characters that can be processed for (;n < mCount; ++n) { PRUnichar nextChar = mReadPointer[n]; - if ((nextChar == aStop) || (nextChar == CSS_ESCAPE) || + if ((nextChar == aStop) || (nextChar == '\\') || (nextChar == '\n') || (nextChar == '\r') || (nextChar == '\f')) { break; } #ifdef CSS_REPORT_PARSE_ERRORS - if (nextChar == '\t') { - mColNumber = ((mColNumber - 1 + TAB_STOP_WIDTH) / TAB_STOP_WIDTH) - * TAB_STOP_WIDTH; - } else { - ++mColNumber; - } + ++mColNumber; #endif } // Add to the token what we have so far @@ -1411,7 +1323,7 @@ nsCSSScanner::ParseString(PRInt32 aStop, nsCSSToken& aToken) #endif break; } - if (ch == CSS_ESCAPE) { + if (ch == '\\') { if (!ParseAndAppendEscape(aToken.mIdent, true)) { aToken.mType = eCSSToken_Bad_String; Pushback(ch); diff --git a/layout/style/nsCSSScanner.h b/layout/style/nsCSSScanner.h index 8fa2025c2721..291887d12638 100644 --- a/layout/style/nsCSSScanner.h +++ b/layout/style/nsCSSScanner.h @@ -47,13 +47,9 @@ #include "mozilla/css/Loader.h" #include "nsCSSStyleSheet.h" -class nsIUnicharInputStream; - // XXX turn this off for minimo builds #define CSS_REPORT_PARSE_ERRORS -#define CSS_BUFFER_SIZE 256 - // for #ifdef CSS_REPORT_PARSE_ERRORS #include "nsXPIDLString.h" class nsIURI; @@ -141,9 +137,7 @@ class nsCSSScanner { // Init the scanner. // |aLineNumber == 1| is the beginning of a file, use |aLineNumber == 0| // when the line number is unknown. - // Either aInput or (aBuffer and aCount) must be set. - void Init(nsIUnicharInputStream* aInput, - const PRUnichar *aBuffer, PRUint32 aCount, + void Init(const nsAString& aBuffer, nsIURI* aURI, PRUint32 aLineNumber, nsCSSStyleSheet* aSheet, mozilla::css::Loader* aLoader); void Close(); @@ -200,15 +194,7 @@ class nsCSSScanner { // "-1" back so we can read it again as a number.) void Pushback(PRUnichar aChar); - // Reports operating-system level errors, e.g. read failures and - // out of memory. - nsresult GetLowLevelError(); - - // sometimes the parser wants to make note of a low-level error - void SetLowLevelError(nsresult aErrorCode); - protected: - bool EnsureData(); PRInt32 Read(); PRInt32 Peek(); bool LookAhead(PRUnichar aChar); @@ -226,10 +212,6 @@ protected: bool GatherIdent(PRInt32 aChar, nsString& aIdent); - // Only used when input is a stream - nsCOMPtr mInputStream; - PRUnichar mBuffer[CSS_BUFFER_SIZE]; - const PRUnichar *mReadPointer; PRUint32 mOffset; PRUint32 mCount; @@ -237,7 +219,6 @@ protected: PRInt32 mPushbackCount; PRInt32 mPushbackSize; PRUnichar mLocalPushback[4]; - nsresult mLowLevelError; PRUint32 mLineNumber; // True if we are in SVG mode; false in "normal" CSS diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index 5a575aa8259b..f8227179211b 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -621,13 +621,8 @@ nsCSSValue::Array* nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, PRUint32 aNumArgs) { nsRefPtr func = Array::Create(aNumArgs + 1); - if (!func) { - return nsnull; - } - func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated); SetArrayValue(func, eCSSUnit_Function); - return func; } @@ -657,18 +652,20 @@ nsCSSValue::BufferFromString(const nsString& aValue) buffer->AddRef(); return buffer; } - + PRUnichar length = aValue.Length(); // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer. + // NOTE: String buffer allocation is currently fallible. buffer = nsStringBuffer::Alloc((length + 1) * sizeof(PRUnichar)); - if (NS_LIKELY(buffer != 0)) { - PRUnichar* data = static_cast(buffer->Data()); - nsCharTraits::copy(data, aValue.get(), length); - // Null-terminate. - data[length] = 0; + if (NS_UNLIKELY(!buffer)) { + NS_RUNTIMEABORT("out of memory"); } + PRUnichar* data = static_cast(buffer->Data()); + nsCharTraits::copy(data, aValue.get(), length); + // Null-terminate. + data[length] = 0; return buffer; } diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index d2bb4bdb712b..f1d1ddb5cc1c 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -49,7 +49,6 @@ #include "nsString.h" #include "nsStringBuffer.h" #include "nsTArray.h" -#include "mozilla/mozalloc.h" #include "nsStyleConsts.h" class imgIRequest; @@ -554,11 +553,6 @@ struct nsCSSValue::Array { return new (aItemCount) Array(aItemCount); } - static Array* Create(const mozilla::fallible_t& aFallible, - size_t aItemCount) { - return new (aFallible, aItemCount) Array(aItemCount); - } - nsCSSValue& operator[](size_t aIndex) { NS_ABORT_IF_FALSE(aIndex < mCount, "out of range"); return mArray[aIndex]; @@ -619,13 +613,6 @@ private: return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1)); } - void* operator new(size_t aSelfSize, const mozilla::fallible_t& aFallible, - size_t aItemCount) CPP_THROW_NEW { - NS_ABORT_IF_FALSE(aItemCount > 0, "cannot have a 0 item count"); - return ::operator new(aSelfSize + sizeof(nsCSSValue) * (aItemCount - 1), - aFallible); - } - void operator delete(void* aPtr) { ::operator delete(aPtr); } nsCSSValue* First() { return mArray; } @@ -1019,7 +1006,8 @@ nsCSSValue::GetPairListValue() const struct nsCSSValueGradientStop { public: nsCSSValueGradientStop(); - // needed to keep bloat logs happy when we use the nsTArray in nsCSSValueGradient + // needed to keep bloat logs happy when we use the TArray + // in nsCSSValueGradient nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther); ~nsCSSValueGradientStop(); @@ -1052,7 +1040,7 @@ struct nsCSSValueGradient { nsCSSValue mRadialShape; nsCSSValue mRadialSize; - nsTArray mStops; + InfallibleTArray mStops; bool operator==(const nsCSSValueGradient& aOther) const { diff --git a/layout/style/nsIMediaList.h b/layout/style/nsIMediaList.h index ced1b10947eb..ac5d71cca182 100644 --- a/layout/style/nsIMediaList.h +++ b/layout/style/nsIMediaList.h @@ -110,7 +110,7 @@ private: }; struct FeatureEntry { const nsMediaFeature *mFeature; - nsTArray mExpressions; + InfallibleTArray mExpressions; }; nsCOMPtr mMedium; nsTArray mFeatureCache; @@ -192,13 +192,9 @@ public: nsMediaQueryResultCacheKey* aKey); nsresult SetStyleSheet(nsCSSStyleSheet* aSheet); - nsresult AppendQuery(nsAutoPtr& aQuery) { - // Takes ownership of aQuery (if it succeeds) - if (!mArray.AppendElement(aQuery.get())) { - return NS_ERROR_OUT_OF_MEMORY; - } - aQuery.forget(); - return NS_OK; + void AppendQuery(nsAutoPtr& aQuery) { + // Takes ownership of aQuery + mArray.AppendElement(aQuery.forget()); } nsresult Clone(nsMediaList** aResult); @@ -213,7 +209,7 @@ protected: nsresult Delete(const nsAString & aOldMedium); nsresult Append(const nsAString & aOldMedium); - nsTArray > mArray; + InfallibleTArray > mArray; // not refcounted; sheet will let us know when it goes away // mStyleSheet is the sheet that needs to be dirtied when this medialist // changes diff --git a/layout/svg/base/src/nsSVGImageFrame.cpp b/layout/svg/base/src/nsSVGImageFrame.cpp index 1bd37c3b8162..6f306a3e2ff5 100644 --- a/layout/svg/base/src/nsSVGImageFrame.cpp +++ b/layout/svg/base/src/nsSVGImageFrame.cpp @@ -47,6 +47,9 @@ #include "nsIInterfaceRequestorUtils.h" #include "gfxPlatform.h" #include "nsSVGSVGElement.h" +#include "mozilla/Preferences.h" + +using namespace mozilla; class nsSVGImageFrame; @@ -72,14 +75,15 @@ private: nsSVGImageFrame *mFrame; }; +typedef nsSVGPathGeometryFrame nsSVGImageFrameBase; -class nsSVGImageFrame : public nsSVGPathGeometryFrame +class nsSVGImageFrame : public nsSVGImageFrameBase { friend nsIFrame* NS_NewSVGImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGImageFrame(nsStyleContext* aContext) : nsSVGPathGeometryFrame(aContext) {} + nsSVGImageFrame(nsStyleContext* aContext) : nsSVGImageFrameBase(aContext) {} virtual ~nsSVGImageFrame(); public: @@ -168,7 +172,7 @@ nsSVGImageFrame::Init(nsIContent* aContent, NS_ASSERTION(image, "Content is not an SVG image!"); #endif - nsresult rv = nsSVGPathGeometryFrame::Init(aContent, aParent, aPrevInFlow); + nsresult rv = nsSVGImageFrameBase::Init(aContent, aParent, aPrevInFlow); if (NS_FAILED(rv)) return rv; mListener = new nsSVGImageListener(this); @@ -195,18 +199,34 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { - if (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::x || - aAttribute == nsGkAtoms::y || - aAttribute == nsGkAtoms::width || - aAttribute == nsGkAtoms::height || - aAttribute == nsGkAtoms::preserveAspectRatio)) { - nsSVGUtils::UpdateGraphic(this); - return NS_OK; - } + if (aNameSpaceID == kNameSpaceID_None && + (aAttribute == nsGkAtoms::x || + aAttribute == nsGkAtoms::y || + aAttribute == nsGkAtoms::width || + aAttribute == nsGkAtoms::height || + aAttribute == nsGkAtoms::preserveAspectRatio)) { + nsSVGUtils::UpdateGraphic(this); + return NS_OK; + } + if (aNameSpaceID == kNameSpaceID_XLink && + aAttribute == nsGkAtoms::href) { + // If caller is not chrome and dom.disable_image_src_set is true, + // prevent setting image.src by exiting early + if (Preferences::GetBool("dom.disable_image_src_set") && + !nsContentUtils::IsCallerChrome()) { + return NS_OK; + } + nsSVGImageElement *element = static_cast(mContent); - return nsSVGPathGeometryFrame::AttributeChanged(aNameSpaceID, - aAttribute, aModType); + if (element->mStringAttributes[nsSVGImageElement::HREF].IsExplicitlySet()) { + element->LoadSVGImage(true, true); + } else { + element->CancelImageRequests(true); + } + } + + return nsSVGImageFrameBase::AttributeChanged(aNameSpaceID, + aAttribute, aModType); } gfxMatrix @@ -426,7 +446,7 @@ nsSVGImageFrame::GetFrameForPoint(const nsPoint &aPoint) // just fall back on our element's own bounds here. } - return nsSVGPathGeometryFrame::GetFrameForPoint(aPoint); + return nsSVGImageFrameBase::GetFrameForPoint(aPoint); } nsIAtom * diff --git a/layout/tools/reftest/remotereftest.py b/layout/tools/reftest/remotereftest.py index 9ecf5355043c..dcdafd3a8847 100644 --- a/layout/tools/reftest/remotereftest.py +++ b/layout/tools/reftest/remotereftest.py @@ -428,9 +428,6 @@ def main(): automation.setRemoteLog(options.remoteLogFile) reftest = RemoteReftest(automation, dm, options, SCRIPT_DIRECTORY) - # Start the webserver - reftest.startWebServer(options) - # Hack in a symbolic link for jsreftest os.system("ln -s ../jsreftest " + str(os.path.join(SCRIPT_DIRECTORY, "jsreftest"))) @@ -441,6 +438,12 @@ def main(): elif os.path.exists(args[0]): manifestPath = os.path.abspath(args[0]).split(SCRIPT_DIRECTORY)[1].strip('/') manifest = "http://" + str(options.remoteWebServer) + ":" + str(options.httpPort) + "/" + manifestPath + else: + print "ERROR: Could not find test manifest '%s'" % manifest + sys.exit(1) + + # Start the webserver + reftest.startWebServer(options) procName = options.app.split('/')[-1] if (dm.processExist(procName)): diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index b65a07e5404b..0bb7b73e93f0 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -155,7 +155,7 @@ nsMenuPopupFrame::Init(nsIContent* aContent, mMenuCanOverlapOSBar = LookAndFeel::GetInt(LookAndFeel::eIntID_MenusCanOverlapOSBar) != 0; - rv = CreatePopupViewForFrame(); + rv = CreatePopupView(); NS_ENSURE_SUCCESS(rv, rv); // XXX Hack. The popup's view should float above all other views, @@ -1921,24 +1921,20 @@ nsMenuPopupFrame::SetConsumeRollupEvent(PRUint32 aConsumeMode) * as much as possible. Until we get rid of views finally... */ nsresult -nsMenuPopupFrame::CreatePopupViewForFrame() +nsMenuPopupFrame::CreatePopupView() { if (HasView()) { return NS_OK; } - nsViewVisibility visibility = nsViewVisibility_kShow; - PRInt32 zIndex = 0; - bool autoZIndex = false; - - nsIView* parentView; nsIViewManager* viewManager = PresContext()->GetPresShell()->GetViewManager(); NS_ASSERTION(nsnull != viewManager, "null view manager"); // Create a view - parentView = viewManager->GetRootView(); - visibility = nsViewVisibility_kHide; - zIndex = PR_INT32_MAX; + nsIView* parentView = viewManager->GetRootView(); + nsViewVisibility visibility = nsViewVisibility_kHide; + PRInt32 zIndex = PR_INT32_MAX; + bool autoZIndex = false; NS_ASSERTION(parentView, "no parent view"); @@ -1954,7 +1950,7 @@ nsMenuPopupFrame::CreatePopupViewForFrame() SetView(view); NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, - ("nsMenuPopupFrame::CreatePopupViewForFrame: frame=%p view=%p", this, view)); + ("nsMenuPopupFrame::CreatePopupView: frame=%p view=%p", this, view)); if (!view) return NS_ERROR_OUT_OF_MEMORY; diff --git a/layout/xul/base/src/nsMenuPopupFrame.h b/layout/xul/base/src/nsMenuPopupFrame.h index fc564b9c094c..ea8b35ef4b88 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.h +++ b/layout/xul/base/src/nsMenuPopupFrame.h @@ -409,7 +409,7 @@ protected: // Create a popup view for this frame. The view is added a child of the root // view, and is initially hidden. - nsresult CreatePopupViewForFrame(); + nsresult CreatePopupView(); nsString mIncrementalString; // for incremental typing navigation diff --git a/media/libogg/include/ogg/config_types.h b/media/libogg/include/ogg/config_types.h index 00962788e193..1e7d49098909 100644 --- a/media/libogg/include/ogg/config_types.h +++ b/media/libogg/include/ogg/config_types.h @@ -20,6 +20,6 @@ typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; -typedef long ogg_int64_t; +typedef long long ogg_int64_t; #endif diff --git a/media/libsydneyaudio/src/sydney_audio_android.c b/media/libsydneyaudio/src/sydney_audio_android.c index 5ebdc89ae81a..0b6e8ef0bedf 100644 --- a/media/libsydneyaudio/src/sydney_audio_android.c +++ b/media/libsydneyaudio/src/sydney_audio_android.c @@ -59,8 +59,10 @@ struct AudioTrack { jclass class; jmethodID constructor; jmethodID flush; + jmethodID getminbufsz; jmethodID pause; jmethodID play; + jmethodID release; jmethodID setvol; jmethodID stop; jmethodID write; @@ -105,6 +107,7 @@ struct sa_stream { int64_t timePlaying; int64_t amountWritten; unsigned int bufferSize; + unsigned int minBufferSize; jclass at_class; }; @@ -120,8 +123,10 @@ init_jni_bindings(JNIEnv *jenv) { "android/media/AudioTrack")); at.constructor = (*jenv)->GetMethodID(jenv, class, "", "(IIIIII)V"); at.flush = (*jenv)->GetMethodID(jenv, class, "flush", "()V"); + at.getminbufsz = (*jenv)->GetStaticMethodID(jenv, class, "getMinBufferSize", "(III)I"); at.pause = (*jenv)->GetMethodID(jenv, class, "pause", "()V"); at.play = (*jenv)->GetMethodID(jenv, class, "play", "()V"); + at.release = (*jenv)->GetMethodID(jenv, class, "release", "()V"); at.setvol = (*jenv)->GetMethodID(jenv, class, "setStereoVolume", "(FF)I"); at.stop = (*jenv)->GetMethodID(jenv, class, "stop", "()V"); at.write = (*jenv)->GetMethodID(jenv, class, "write", "([BII)I"); @@ -181,7 +186,8 @@ sa_stream_create_pcm( s->timePlaying = 0; s->amountWritten = 0; - s->bufferSize = rate * channels; + s->bufferSize = 0; + s->minBufferSize = 0; *_s = s; return SA_SUCCESS; @@ -199,8 +205,9 @@ sa_stream_open(sa_stream_t *s) { } JNIEnv *jenv = GetJNIForThread(); - if (!jenv) + if (!jenv) { return SA_ERROR_NO_DEVICE; + } if ((*jenv)->PushLocalFrame(jenv, 4)) { return SA_ERROR_OOM; @@ -211,6 +218,21 @@ sa_stream_open(sa_stream_t *s) { int32_t chanConfig = s->channels == 1 ? CHANNEL_OUT_MONO : CHANNEL_OUT_STEREO; + jint minsz = (*jenv)->CallStaticIntMethod(jenv, s->at_class, at.getminbufsz, + s->rate, chanConfig, ENCODING_PCM_16BIT); + if (minsz <= 0) { + (*jenv)->DeleteGlobalRef(jenv, s->at_class); + (*jenv)->PopLocalFrame(jenv, NULL); + return SA_ERROR_INVALID; + } + + s->minBufferSize = minsz; + + s->bufferSize = s->rate * s->channels * sizeof(int16_t); + if (s->bufferSize < s->minBufferSize) { + s->bufferSize = s->minBufferSize; + } + jobject obj = (*jenv)->NewObject(jenv, s->at_class, at.constructor, STREAM_MUSIC, @@ -238,7 +260,7 @@ sa_stream_open(sa_stream_t *s) { s->output_unit = (*jenv)->NewGlobalRef(jenv, obj); (*jenv)->PopLocalFrame(jenv, NULL); - ALOG("%x - New stream %d %d", s, s->rate, s->channels); + ALOG("%p - New stream %u %u bsz=%u min=%u", s, s->rate, s->channels, s->bufferSize, s->minBufferSize); return SA_SUCCESS; } @@ -251,14 +273,18 @@ sa_stream_destroy(sa_stream_t *s) { } JNIEnv *jenv = GetJNIForThread(); - if (!jenv) + if (!jenv) { return SA_SUCCESS; + } + (*jenv)->CallVoidMethod(jenv, s->output_unit, at.stop); + (*jenv)->CallVoidMethod(jenv, s->output_unit, at.flush); + (*jenv)->CallVoidMethod(jenv, s->output_unit, at.release); (*jenv)->DeleteGlobalRef(jenv, s->output_unit); (*jenv)->DeleteGlobalRef(jenv, s->at_class); free(s); - ALOG("%x - Stream destroyed", s); + ALOG("%p - Stream destroyed", s); return SA_SUCCESS; } @@ -290,16 +316,11 @@ sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) { return SA_ERROR_OOM; } - jbyte *byte = (*jenv)->GetByteArrayElements(jenv, bytearray, NULL); - if (!byte) { - (*jenv)->PopLocalFrame(jenv, NULL); - return SA_ERROR_OOM; - } - - memcpy(byte, data, nbytes); + (*jenv)->SetByteArrayRegion(jenv, bytearray, 0, nbytes, data); size_t wroteSoFar = 0; jint retval; + int first = 1; do { retval = (*jenv)->CallIntMethod(jenv, @@ -309,27 +330,27 @@ sa_stream_write(sa_stream_t *s, const void *data, size_t nbytes) { wroteSoFar, nbytes - wroteSoFar); if (retval < 0) { - ALOG("%x - Write failed %d", s, retval); + ALOG("%p - Write failed %d", s, retval); break; } wroteSoFar += retval; + /* android doesn't start playing until we explictly call play. */ + if (first && !s->isPaused) { + sa_stream_resume(s); + first = 0; + } + if (wroteSoFar != nbytes) { - - /* android doesn't start playing until we explictly call play. */ - if (!s->isPaused) - sa_stream_resume(s); - struct timespec ts = {0, 100000000}; /* .10s */ nanosleep(&ts, NULL); } } while(wroteSoFar < nbytes); + ALOG("%p - Wrote %u", s, nbytes); s->amountWritten += nbytes; - (*jenv)->ReleaseByteArrayElements(jenv, bytearray, byte, 0); - (*jenv)->PopLocalFrame(jenv, NULL); return retval < 0 ? SA_ERROR_INVALID : SA_SUCCESS; @@ -352,9 +373,9 @@ sa_stream_get_write_size(sa_stream_t *s, size_t *size) { /* No android API for this, so estimate based on how much we have played and * how much we have written. */ - *size = s->bufferSize - ((s->timePlaying * s->channels * s->rate / - MILLISECONDS_PER_SECOND) - s->amountWritten); - ALOG("%x - Write Size %d", s, *size); + *size = s->bufferSize - ((s->timePlaying * s->channels * s->rate * sizeof(int16_t) / + MILLISECONDS_PER_SECOND) - s->amountWritten); + ALOG("%p - Write Size tp=%lld aw=%u sz=%zu", s, s->timePlaying, s->amountWritten, *size); return SA_SUCCESS; } @@ -367,7 +388,7 @@ sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) { return SA_ERROR_NO_INIT; } - ALOG("%x - get position", s); + ALOG("%p - get position", s); JNIEnv *jenv = GetJNIForThread(); *pos = (*jenv)->CallIntMethod(jenv, s->output_unit, at.getpos); @@ -398,7 +419,7 @@ sa_stream_pause(sa_stream_t *s) { int64_t ticker = current_time.tv_sec * 1000 + current_time.tv_nsec / 1000000; s->timePlaying += ticker - s->lastStartTime; } - ALOG("%x - Pause total time playing: %lld total written: %lld", s, s->timePlaying, s->amountWritten); + ALOG("%p - Pause total time playing: %lld total written: %lld", s, s->timePlaying, s->amountWritten); (*jenv)->CallVoidMethod(jenv, s->output_unit, at.pause); return SA_SUCCESS; @@ -412,7 +433,7 @@ sa_stream_resume(sa_stream_t *s) { return SA_ERROR_NO_INIT; } - ALOG("%x - resume", s); + ALOG("%p - resume", s); JNIEnv *jenv = GetJNIForThread(); s->isPaused = 0; @@ -435,15 +456,25 @@ sa_stream_drain(sa_stream_t *s) return SA_ERROR_NO_INIT; } - /* There is no way with the Android SDK to determine exactly how - long to playback. So estimate and sleep for the long. - */ - +/* This is somewhat of a hack (see bug 693131). The AudioTrack documentation + doesn't make it clear how much data must be written before a chunk of data is + played, and experimentation with short streams required filling the entire + allocated buffer. To guarantee that short streams (and the end of longer + streams) are audible, fill the remaining space in the AudioTrack with silence + before sleeping. Note that the sleep duration is calculated from the + duration of audio written before filling the buffer with silence. */ size_t available; sa_stream_get_write_size(s, &available); - long x = (s->bufferSize - available) * 1000 / s->channels / s->rate / sizeof(int16_t) * NANOSECONDS_IN_MILLISECOND; - ALOG("%x - Drain - sleep for %f ns", s, x); + void *p = calloc(1, available); + sa_stream_write(s, p, available); + free(p); + + /* There is no way with the Android SDK to determine exactly how + long to playback. So estimate and sleep for the long. */ + long x = (s->bufferSize - available) * 1000 / s->channels / s->rate / + sizeof(int16_t) * NANOSECONDS_IN_MILLISECOND; + ALOG("%p - Drain - flush %u, sleep for %ld ns", s, available, x); struct timespec ts = {0, x}; nanosleep(&ts, NULL); diff --git a/mobile/app/mobile.js b/mobile/app/mobile.js index 8f377b1c38f9..b5a63a80922b 100644 --- a/mobile/app/mobile.js +++ b/mobile/app/mobile.js @@ -376,9 +376,7 @@ pref("privacy.item.geolocation", true); pref("privacy.item.siteSettings", true); pref("privacy.item.syncAccount", true); -#ifdef MOZ_PLATFORM_MAEMO pref("plugins.force.wmode", "opaque"); -#endif // URL to the Learn More link XXX this is the firefox one. Bug 495578 fixes this. pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/firefox/geolocation/"); diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 728fd7c83842..9d7ca6b4f2fa 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3291,6 +3291,7 @@ pref("webgl.verbose", false); pref("webgl.prefer-native-gl", false); pref("webgl.min_capability_mode", false); pref("webgl.disable-extensions", false); +pref("webgl.msaa-level", 2); #ifdef XP_WIN // The default TCP send window on Windows is too small, and autotuning only occurs on receive diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index 0c5051cc33df..30ac953885bc 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -171,7 +171,8 @@ public: PRInt32 MemoryCacheCapacity(); PRInt32 MemoryCacheMaxEntrySize() { return mMemoryCacheMaxEntrySize; } - static PRUint32 GetSmartCacheSize(const nsAString& cachePath); + static PRUint32 GetSmartCacheSize(const nsAString& cachePath, + PRUint32 currentSize); private: bool PermittedToSmartSize(nsIPrefBranch*, bool firstRun); @@ -200,8 +201,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver) class nsSetSmartSizeEvent: public nsRunnable { public: - nsSetSmartSizeEvent(bool firstRun, PRInt32 smartSize) - : mFirstRun(firstRun) , mSmartSize(smartSize) {} + nsSetSmartSizeEvent(PRInt32 smartSize) + : mSmartSize(smartSize) {} NS_IMETHOD Run() { @@ -226,8 +227,6 @@ public: smartSizeEnabled = false; if (smartSizeEnabled) { nsCacheService::SetDiskCacheCapacity(mSmartSize); - // also set on observer, in case mDiskDevice not init'd yet. - nsCacheService::gService->mObserver->SetDiskCacheCapacity(mSmartSize); rv = branch->SetIntPref(DISK_CACHE_SMART_SIZE_PREF, mSmartSize); if (NS_FAILED(rv)) NS_WARNING("Failed to set smart size pref"); @@ -235,8 +234,7 @@ public: return rv; } -private: - bool mFirstRun; +private: PRInt32 mSmartSize; }; @@ -245,28 +243,25 @@ private: class nsGetSmartSizeEvent: public nsRunnable { public: - nsGetSmartSizeEvent(bool firstRun, const nsAString& cachePath) - : mFirstRun(firstRun) - , mCachePath(cachePath) - , mSmartSize(0) + nsGetSmartSizeEvent(const nsAString& cachePath, PRUint32 currentSize) + : mCachePath(cachePath) + , mCurrentSize(currentSize) {} // Calculates user's disk space available on a background thread and // dispatches this value back to the main thread. NS_IMETHOD Run() { - mSmartSize = - nsCacheProfilePrefObserver::GetSmartCacheSize(mCachePath); - nsCOMPtr event = new nsSetSmartSizeEvent(mFirstRun, - mSmartSize); - NS_DispatchToMainThread(event); + PRUint32 size; + size = nsCacheProfilePrefObserver::GetSmartCacheSize(mCachePath, + mCurrentSize); + NS_DispatchToMainThread(new nsSetSmartSizeEvent(size)); return NS_OK; } -private: - bool mFirstRun; +private: nsString mCachePath; - PRInt32 mSmartSize; + PRUint32 mCurrentSize; }; class nsBlockOnCacheThreadEvent : public nsRunnable { @@ -435,18 +430,7 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject, return rv; PRInt32 newCapacity = 0; if (smartSizeEnabled) { - // Dispatch event to update smart size: just keep using old - // value if this fails at any point - if (!mDiskCacheParentDirectory) - return NS_ERROR_NOT_AVAILABLE; // disk cache disabled anyway - nsAutoString cachePath; - rv = mDiskCacheParentDirectory->GetPath(cachePath); - if (NS_FAILED(rv)) - return rv; - // Smart sizing switched on: recalculate the capacity. - nsCOMPtr event = - new nsGetSmartSizeEvent(false, cachePath); - rv = nsCacheService::DispatchToCacheIOThread(event); + nsCacheService::SetDiskSmartSize(); } else { // Smart sizing switched off: use user specified size rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &newCapacity); @@ -559,6 +543,42 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject, return NS_OK; } +// Returns default ("smart") size (in KB) of cache, given available disk space +// (also in KB) +static PRUint32 +SmartCacheSize(const PRUint32 availKB) +{ + if (availKB > 100 * 1024 * 1024) + return MAX_CACHE_SIZE; // skip computing if we're over 100 GB + + // Grow/shrink in 10 MB units, deliberately, so that in the common case we + // don't shrink cache and evict items every time we startup (it's important + // that we don't slow down startup benchmarks). + PRUint32 sz10MBs = 0; + PRUint32 avail10MBs = availKB / (1024*10); + + // .5% of space above 25 GB + if (avail10MBs > 2500) { + sz10MBs += (avail10MBs - 2500)*.005; + avail10MBs = 2500; + } + // 1% of space between 7GB -> 25 GB + if (avail10MBs > 700) { + sz10MBs += (avail10MBs - 700)*.01; + avail10MBs = 700; + } + // 5% of space between 500 MB -> 7 GB + if (avail10MBs > 50) { + sz10MBs += (avail10MBs - 50)*.05; + avail10MBs = 50; + } + + // 40% of space up to 500 MB (50 MB min) + sz10MBs += NS_MAX(5, avail10MBs * .4); + + return NS_MIN(MAX_CACHE_SIZE, sz10MBs * 10 * 1024); +} + /* Computes our best guess for the default size of the user's disk cache, * based on the amount of space they have free on their hard drive. * We use a tiered scheme: the more space available, @@ -571,45 +591,24 @@ nsCacheProfilePrefObserver::Observe(nsISupports * subject, *@return: The size that the user's disk cache should default to, in kBytes. */ PRUint32 -nsCacheProfilePrefObserver::GetSmartCacheSize(const nsAString& cachePath) +nsCacheProfilePrefObserver::GetSmartCacheSize(const nsAString& cachePath, + PRUint32 currentSize) { - // Check for free space on device where cache directory lives - nsresult rv; - nsCOMPtr - cacheDirectory (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv)); - if (NS_FAILED(rv) || !cacheDirectory) - return DEFAULT_CACHE_SIZE; - rv = cacheDirectory->InitWithPath(cachePath); - if (NS_FAILED(rv)) - return DEFAULT_CACHE_SIZE; - PRInt64 bytesAvailable; - rv = cacheDirectory->GetDiskSpaceAvailable(&bytesAvailable); - if (NS_FAILED(rv)) - return DEFAULT_CACHE_SIZE; - PRInt64 kBytesAvail = bytesAvailable / 1024; - - // 0 MB <= Available < 500 MB: Use between 50MB and 200MB - if (kBytesAvail < DEFAULT_CACHE_SIZE * 2) - return NS_MAX(MIN_CACHE_SIZE, kBytesAvail * 4 / 10); - - // 500MB <= Available < 2.5 GB: Use 250MB - if (kBytesAvail < static_cast(DEFAULT_CACHE_SIZE) * 10) - return DEFAULT_CACHE_SIZE; + // Check for free space on device where cache directory lives + nsresult rv; + nsCOMPtr + cacheDirectory (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv)); + if (NS_FAILED(rv) || !cacheDirectory) + return DEFAULT_CACHE_SIZE; + rv = cacheDirectory->InitWithPath(cachePath); + if (NS_FAILED(rv)) + return DEFAULT_CACHE_SIZE; + PRInt64 bytesAvailable; + rv = cacheDirectory->GetDiskSpaceAvailable(&bytesAvailable); + if (NS_FAILED(rv)) + return DEFAULT_CACHE_SIZE; - // 2.5 GB <= Available < 5 GB: Use between 250MB and 500MB - if (kBytesAvail < static_cast(DEFAULT_CACHE_SIZE) * 20) - return kBytesAvail / 10; - - // 5 GB <= Available < 50 GB: Use 625MB - if (kBytesAvail < static_cast(DEFAULT_CACHE_SIZE) * 200 ) - return DEFAULT_CACHE_SIZE * 5 / 2; - - // 50 GB <= Available < 75 GB: Use 800MB - if (kBytesAvail < static_cast(DEFAULT_CACHE_SIZE) * 300) - return DEFAULT_CACHE_SIZE / 5 * 16; - - // Use 1 GB - return MAX_CACHE_SIZE; + return SmartCacheSize((bytesAvailable / 1024) + currentSize); } /* Determine if we are permitted to dynamically size the user's disk cache based @@ -733,13 +732,6 @@ nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch) mDiskCacheCapacity = DEFAULT_CACHE_SIZE; } } - nsAutoString cachePath; - rv = mDiskCacheParentDirectory->GetPath(cachePath); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr event = - new nsGetSmartSizeEvent(!!firstSmartSizeRun, cachePath); - nsCacheService::DispatchToCacheIOThread(event); - } } if (firstSmartSizeRun) { @@ -1369,6 +1361,9 @@ nsCacheService::CreateDiskDevice() delete mDiskDevice; mDiskDevice = nsnull; } + + SetDiskSmartSize_Locked(true); + return rv; } @@ -2555,3 +2550,49 @@ nsCacheService::OnEnterExitPrivateBrowsing() gService->mMemoryDevice->EvictEntries(nsnull); } } + +nsresult +nsCacheService::SetDiskSmartSize() +{ + nsCacheServiceAutoLock lock; + + if (!gService) return NS_ERROR_NOT_AVAILABLE; + + return gService->SetDiskSmartSize_Locked(false); +} + +nsresult +nsCacheService::SetDiskSmartSize_Locked(bool checkPref) +{ + nsresult rv; + + if (!mObserver->DiskCacheParentDirectory()) + return NS_ERROR_NOT_AVAILABLE; + + if (!mDiskDevice) + return NS_ERROR_NOT_AVAILABLE; + + if (checkPref) { + nsCOMPtr branch = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (!branch) return NS_ERROR_FAILURE; + + bool smartSizeEnabled; + rv = branch->GetBoolPref(DISK_CACHE_SMART_SIZE_ENABLED_PREF, + &smartSizeEnabled); + + if (NS_FAILED(rv) || !smartSizeEnabled) + return NS_ERROR_NOT_AVAILABLE; + } + + nsAutoString cachePath; + rv = mObserver->DiskCacheParentDirectory()->GetPath(cachePath); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr event = + new nsGetSmartSizeEvent(cachePath, mDiskDevice->getCacheSize()); + DispatchToCacheIOThread(event); + } else { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} diff --git a/netwerk/cache/nsCacheService.h b/netwerk/cache/nsCacheService.h index 702c4c42415c..7ef0aca6d8fc 100644 --- a/netwerk/cache/nsCacheService.h +++ b/netwerk/cache/nsCacheService.h @@ -178,6 +178,9 @@ public: static void OnEnterExitPrivateBrowsing(); + // Starts smart cache size computation if disk device is available + static nsresult SetDiskSmartSize(); + nsresult Init(); void Shutdown(); @@ -258,6 +261,8 @@ private: void LogCacheStatistics(); #endif + nsresult SetDiskSmartSize_Locked(bool checkPref); + /** * Data Members */ diff --git a/security/coreconf/SunOS5.mk b/security/coreconf/SunOS5.mk index c3f8e182533d..43b526d9707b 100644 --- a/security/coreconf/SunOS5.mk +++ b/security/coreconf/SunOS5.mk @@ -37,15 +37,6 @@ include $(CORE_DEPTH)/coreconf/UNIX.mk -# -# Temporary define for the Client; to be removed when binary release is used -# -ifdef MOZILLA_CLIENT - ifndef NS_USE_NATIVE - NS_USE_GCC = 1 - endif -endif - # Sun's WorkShop defines v8, v8plus and v9 architectures. # gcc on Solaris defines v8 and v9 "cpus". # gcc's v9 is equivalent to Workshop's v8plus. diff --git a/security/coreconf/coreconf.dep b/security/coreconf/coreconf.dep index b536cfc01b91..b75161110bb5 100644 --- a/security/coreconf/coreconf.dep +++ b/security/coreconf/coreconf.dep @@ -42,4 +42,3 @@ */ #error "Do not include this header file." - diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 6c6bb96eabaa..cbf29ab867cd 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_13_RC0 +NSS_3_13_1_BETA1 diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 9495a41292e2..4066aa3f066d 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -36,7 +36,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id: nss.h,v 1.84 2011/10/04 22:56:31 wtc%google.com Exp $ */ +/* $Id: nss.h,v 1.85 2011/10/14 00:16:09 wtc%google.com Exp $ */ #ifndef __nss_h_ #define __nss_h_ @@ -66,12 +66,12 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.13.0.0" _NSS_ECC_STRING _NSS_CUSTOMIZED +#define NSS_VERSION "3.13.1.0" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 #define NSS_VMINOR 13 -#define NSS_VPATCH 0 +#define NSS_VPATCH 1 #define NSS_VBUILD 0 -#define NSS_BETA PR_FALSE +#define NSS_BETA PR_TRUE #ifndef RC_INVOKED diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index 7d8c90df84b6..b2f151d82ecd 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -36,7 +36,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id: nssinit.c,v 1.112 2011/10/04 02:35:58 emaldona%redhat.com Exp $ */ +/* $Id: nssinit.c,v 1.114 2011/10/18 19:03:31 wtc%google.com Exp $ */ #include #include @@ -540,13 +540,13 @@ nss_doLockInit(void) { nssInitLock = PZ_NewLock(nssILockOther); if (nssInitLock == NULL) { - return (PRStatus) SECFailure; + return PR_FAILURE; } nssInitCondition = PZ_NewCondVar(nssInitLock); if (nssInitCondition == NULL) { - return (PRStatus) SECFailure; + return PR_FAILURE; } - return (PRStatus) SECSuccess; + return PR_SUCCESS; } @@ -577,10 +577,10 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, return SECSuccess; } - /* make sure our locks are initialized one and only one time */ - rv = PR_CallOnce(&nssInitOnce, nss_doLockInit); - if (rv != SECSuccess) { - return rv; + /* make sure our lock and condition variable are initialized one and only + * one time */ + if (PR_CallOnce(&nssInitOnce, nss_doLockInit) != PR_SUCCESS) { + return SECFailure; } /* @@ -597,7 +597,6 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, /* once we've completed basic initialization, we can allow more than * one process initialize NSS at a time. */ } - /* get the current value */ nssIsInInit++; PZ_Unlock(nssInitLock); @@ -761,6 +760,11 @@ loser: PR_smprintf_free(configStrings); } } + PZ_Lock(nssInitLock); + nssIsInInit--; + /* We failed to init, allow one to move forward */ + PZ_NotifyCondVar(nssInitCondition); + PZ_Unlock(nssInitLock); return SECFailure; } diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index a9a015ec4c42..84d1f66d0ed6 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -57,11 +57,11 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.13.0.0" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.13.1.0" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 13 -#define SOFTOKEN_VPATCH 0 +#define SOFTOKEN_VPATCH 1 #define SOFTOKEN_VBUILD 0 -#define SOFTOKEN_BETA PR_FALSE +#define SOFTOKEN_BETA PR_TRUE #endif /* _SOFTKVER_H_ */ diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index bd5b4dd8cf36..5877d87eb677 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -51,12 +51,12 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.13.0.0" +#define NSSUTIL_VERSION "3.13.1.0 Beta" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 13 -#define NSSUTIL_VPATCH 0 +#define NSSUTIL_VPATCH 1 #define NSSUTIL_VBUILD 0 -#define NSSUTIL_BETA PR_FALSE +#define NSSUTIL_BETA PR_TRUE SEC_BEGIN_PROTOS diff --git a/testing/mochitest/chrome/Makefile.in b/testing/mochitest/chrome/Makefile.in index 029fd045a4b2..e7018f2831f7 100644 --- a/testing/mochitest/chrome/Makefile.in +++ b/testing/mochitest/chrome/Makefile.in @@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk _STATIC_FILES = test_sample.xul \ test_sanityChromeUtils.xul \ + test_sanityPluginUtils.html \ # Disabled until bug 652494 is resolved. # test_sanityException.xul \ # test_sanityException2.xul \ diff --git a/testing/mochitest/tests/test_sanityPluginUtils.html b/testing/mochitest/chrome/test_sanityPluginUtils.html similarity index 77% rename from testing/mochitest/tests/test_sanityPluginUtils.html rename to testing/mochitest/chrome/test_sanityPluginUtils.html index f23f70a3e5d2..b236c87090b8 100644 --- a/testing/mochitest/tests/test_sanityPluginUtils.html +++ b/testing/mochitest/chrome/test_sanityPluginUtils.html @@ -1,16 +1,15 @@ - Profiling test suite for PluginUtils - + - - + + diff --git a/testing/mochitest/jar.mn b/testing/mochitest/jar.mn index 3082e27cd133..64aac8246335 100644 --- a/testing/mochitest/jar.mn +++ b/testing/mochitest/jar.mn @@ -18,7 +18,6 @@ mochikit.jar: content/tests/SimpleTest/ChromeUtils.js (tests/SimpleTest/ChromeUtils.js) content/tests/SimpleTest/MozillaLogger.js (tests/SimpleTest/MozillaLogger.js) content/tests/SimpleTest/LogController.js (tests/SimpleTest/LogController.js) - content/tests/SimpleTest/PluginUtils.js (tests/SimpleTest/PluginUtils.js) content/tests/SimpleTest/setup.js (tests/SimpleTest/setup.js) content/tests/SimpleTest/SimpleTest.js (tests/SimpleTest/SimpleTest.js) content/tests/SimpleTest/test.css (tests/SimpleTest/test.css) diff --git a/testing/mochitest/specialpowers/content/specialpowers.js b/testing/mochitest/specialpowers/content/specialpowers.js index 2646b54c0ee7..b2805de9d35d 100644 --- a/testing/mochitest/specialpowers/content/specialpowers.js +++ b/testing/mochitest/specialpowers/content/specialpowers.js @@ -127,8 +127,9 @@ function attachSpecialPowersToWindow(aWindow) { (aWindow.parent !== null) && (aWindow.parent !== undefined) && (aWindow.parent.wrappedJSObject.SpecialPowers) && - !(aWindow.wrappedJSObject.SpecialPowers)) { - aWindow.wrappedJSObject.SpecialPowers = aWindow.parent.SpecialPowers; + !(aWindow.wrappedJSObject.SpecialPowers) && + aWindow.location.hostname == aWindow.parent.location.hostname) { + aWindow.wrappedJSObject.SpecialPowers = aWindow.parent.wrappedJSObject.SpecialPowers; } else if ((aWindow !== null) && (aWindow !== undefined) && diff --git a/testing/mochitest/tests/Makefile.in b/testing/mochitest/tests/Makefile.in index 254d30c62a8a..2e110a83e9b7 100644 --- a/testing/mochitest/tests/Makefile.in +++ b/testing/mochitest/tests/Makefile.in @@ -64,7 +64,7 @@ _TEST_FILES = \ ifneq ($(OS_TARGET),Android) # Disabled on Android for permaorange, see bug 688052 - _TEST_FILES += test_sanityPluginUtils.html \ + _TEST_FILES += \ test_sanityEventUtils.html \ test_sanitySimpletest.html endif diff --git a/testing/mochitest/tests/SimpleTest/ChromeUtils.js b/testing/mochitest/tests/SimpleTest/ChromeUtils.js index 73a1a544f4ab..41e53257dbcc 100644 --- a/testing/mochitest/tests/SimpleTest/ChromeUtils.js +++ b/testing/mochitest/tests/SimpleTest/ChromeUtils.js @@ -275,4 +275,32 @@ function synthesizeDrop(srcElement, destElement, dragData, dropEffect, aWindow, } finally { ds.endDragSession(true); } -} +}; + +var PluginUtils = +{ + withTestPlugin : function(callback) + { + if (typeof Components == "undefined") + { + todo(false, "Not a Mozilla-based browser"); + return false; + } + + var ph = Components.classes["@mozilla.org/plugin/host;1"] + .getService(Components.interfaces.nsIPluginHost); + var tags = ph.getPluginTags(); + + // Find the test plugin + for (var i = 0; i < tags.length; i++) + { + if (tags[i].name == "Test Plug-in") + { + callback(tags[i]); + return true; + } + } + todo(false, "Need a test plugin on this platform"); + return false; + } +}; diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index 4c542e487539..91d0f2fd9c46 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -44,9 +44,6 @@ function sendMouseEvent(aEvent, aTarget, aWindow) { aTarget = aWindow.document.getElementById(aTarget); } - // For events to trigger the UA's default actions they need to be "trusted" - netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserWrite'); - var event = aWindow.document.createEvent('MouseEvent'); var typeArg = aEvent.type; @@ -72,7 +69,7 @@ function sendMouseEvent(aEvent, aTarget, aWindow) { ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, buttonArg, relatedTargetArg); - aTarget.dispatchEvent(event); + SpecialPowers.dispatchEvent(aWindow, aTarget, event); } /** @@ -145,14 +142,11 @@ function __doEventDispatch(aTarget, aCharCode, aKeyCode, aHasShift) { aTarget = "target"; } - // Make our events trusted - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var event = document.createEvent("KeyEvents"); event.initKeyEvent("keydown", true, true, document.defaultView, false, false, aHasShift, false, aKeyCode, 0); - var accepted = $(aTarget).dispatchEvent(event); + var accepted = SpecialPowers.dispatchEvent(window, aTarget, event); // Preventing the default keydown action also prevents the default // keypress action. @@ -169,14 +163,14 @@ function __doEventDispatch(aTarget, aCharCode, aKeyCode, aHasShift) { if (!accepted) { event.preventDefault(); } - accepted = $(aTarget).dispatchEvent(event); + accepted = SpecialPowers.dispatchEvent(window, aTarget, event); // Always send keyup var event = document.createEvent("KeyEvents"); event.initKeyEvent("keyup", true, true, document.defaultView, false, false, aHasShift, false, aKeyCode, 0); - $(aTarget).dispatchEvent(event); + SpecialPowers.dispatchEvent(window, aTarget, event); return accepted; } diff --git a/testing/mochitest/tests/SimpleTest/Makefile.in b/testing/mochitest/tests/SimpleTest/Makefile.in index 2900692b7606..87502e97b66a 100644 --- a/testing/mochitest/tests/SimpleTest/Makefile.in +++ b/testing/mochitest/tests/SimpleTest/Makefile.in @@ -51,7 +51,6 @@ _SIMPLETEST_FILES = MozillaLogger.js \ EventUtils.js \ ChromeUtils.js \ WindowSnapshot.js \ - PluginUtils.js \ specialpowersAPI.js \ SpecialPowersObserverAPI.js \ $(DEPTH)/toolkit/content/tests/browser/common/mockObjects.js \ diff --git a/testing/mochitest/tests/SimpleTest/PluginUtils.js b/testing/mochitest/tests/SimpleTest/PluginUtils.js deleted file mode 100644 index d6535759e091..000000000000 --- a/testing/mochitest/tests/SimpleTest/PluginUtils.js +++ /dev/null @@ -1,28 +0,0 @@ -var PluginUtils = -{ - withTestPlugin : function(callback) - { - if (typeof Components == "undefined") - { - todo(false, "Not a Mozilla-based browser"); - return false; - } - - netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); - var ph = Components.classes["@mozilla.org/plugin/host;1"] - .getService(Components.interfaces.nsIPluginHost); - var tags = ph.getPluginTags(); - - // Find the test plugin - for (var i = 0; i < tags.length; i++) - { - if (tags[i].name == "Test Plug-in") - { - callback(tags[i]); - return true; - } - } - todo(false, "Need a test plugin on this platform"); - return false; - } -}; diff --git a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js index b662ed8c5b46..592c43365898 100644 --- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js +++ b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js @@ -723,5 +723,15 @@ SpecialPowersAPI.prototype = { registerFactory); return {'cid':cid, 'originalFactory':oldFactory}; }, + + _getElement: function(aWindow, id) { + return ((typeof(id) == "string") ? + aWindow.document.getElementById(id) : id); + }, + + dispatchEvent: function(aWindow, target, event) { + var el = this._getElement(aWindow, target); + return el.dispatchEvent(event); + }, }; diff --git a/toolkit/components/telemetry/TelemetryPing.js b/toolkit/components/telemetry/TelemetryPing.js index d86a297665d0..4284abc216bd 100644 --- a/toolkit/components/telemetry/TelemetryPing.js +++ b/toolkit/components/telemetry/TelemetryPing.js @@ -75,9 +75,12 @@ function getLocale() { getSelectedLocale('global'); } -XPCOMUtils.defineLazyGetter(this, "Telemetry", function () { - return Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); -}); +XPCOMUtils.defineLazyServiceGetter(this, "Telemetry", + "@mozilla.org/base/telemetry;1", + "nsITelemetry"); +XPCOMUtils.defineLazyServiceGetter(this, "idleService", + "@mozilla.org/widget/idleservice;1", + "nsIIdleService"); /** * Returns a set of histograms that can be converted into JSON @@ -346,7 +349,7 @@ TelemetryPing.prototype = { Services.obs.removeObserver(this, "idle-daily"); Services.obs.removeObserver(this, "cycle-collector-begin"); if (this._isIdleObserver) { - idle.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS); + idleService.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS); this._isIdleObserver = false; } }, @@ -431,7 +434,7 @@ TelemetryPing.prototype = { // Notify that data should be gathered now, since ping will happen soon. Services.obs.notifyObservers(null, "gather-telemetry", null); // The ping happens at the first idle of length IDLE_TIMEOUT_SECONDS. - idle.addIdleObserver(this, IDLE_TIMEOUT_SECONDS); + idleService.addIdleObserver(this, IDLE_TIMEOUT_SECONDS); this._isIdleObserver = true; }).bind(this), Ci.nsIThread.DISPATCH_NORMAL); break; @@ -440,7 +443,7 @@ TelemetryPing.prototype = { // fall through case "idle": if (this._isIdleObserver) { - idle.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS); + idleService.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS); this._isIdleObserver = false; } this.send(aTopic == "idle" ? "idle-daily" : aTopic, server); diff --git a/view/public/nsIView.h b/view/public/nsIView.h index 02dd1d67ac41..0c1fc9575f08 100644 --- a/view/public/nsIView.h +++ b/view/public/nsIView.h @@ -62,14 +62,8 @@ enum nsViewVisibility { }; #define NS_IVIEW_IID \ - { 0xe0a3b0ee, 0x8d0f, 0x4dcb, \ - { 0x89, 0x04, 0x81, 0x2d, 0xfd, 0x90, 0x00, 0x73 } } - -// Public view flags are defined in this file -#define NS_VIEW_FLAGS_PUBLIC 0x00FF -// Private view flags are private to the view module, -// and are defined in nsView.h -#define NS_VIEW_FLAGS_PRIVATE 0xFF00 + { 0x7caf32d2, 0xd82a, 0x4b9f, \ + { 0x84, 0xc1, 0xbd, 0x20, 0xeb, 0x5c, 0x78, 0x55 } } // Public view flags @@ -84,15 +78,6 @@ enum nsViewVisibility { // is z-index:auto also #define NS_VIEW_FLAG_TOPMOST 0x0010 -struct nsViewZIndex { - bool mIsAuto; - PRInt32 mZIndex; - bool mIsTopmost; - - nsViewZIndex(bool aIsAuto, PRInt32 aZIndex, bool aIsTopmost) - : mIsAuto(aIsAuto), mZIndex(aZIndex), mIsTopmost(aIsTopmost) {} -}; - //---------------------------------------------------------------------- /** @@ -234,19 +219,6 @@ public: */ nsViewVisibility GetVisibility() const { return mVis; } - /** - * Called to query the z-index of a view. - * The z-index is relative to all siblings of the view. - * @result mZIndex: explicit z-index value or 0 if none is set - * mIsAuto: true if the view is zindex:auto - * mIsTopMost: used when this view is zindex:auto - * true if the view is topmost when compared - * with another z-index:auto view - */ - nsViewZIndex GetZIndex() const { return nsViewZIndex((mVFlags & NS_VIEW_FLAG_AUTO_ZINDEX) != 0, - mZIndex, - (mVFlags & NS_VIEW_FLAG_TOPMOST) != 0); } - /** * Get whether the view "floats" above all other views, * which tells the compositor not to consider higher views in diff --git a/view/public/nsIViewManager.h b/view/public/nsIViewManager.h index 51084008ce24..4dea219f1476 100644 --- a/view/public/nsIViewManager.h +++ b/view/public/nsIViewManager.h @@ -405,7 +405,4 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewManager, NS_IVIEWMANAGER_IID) // synchronously updates the window(s) right away before returning #define NS_VMREFRESH_IMMEDIATE 0x0002 -//animate scroll operation -#define NS_VMREFRESH_SMOOTHSCROLL 0x0008 - #endif // nsIViewManager_h___ diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 48f812a69ad8..18a6b780d9ba 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -360,16 +360,6 @@ void nsIView::SetInvalidationDimensions(const nsRect* aRect) return Impl()->SetInvalidationDimensions(aRect); } -void nsView::SetPositionIgnoringChildWidgets(nscoord aX, nscoord aY) -{ - mDimBounds.x += aX - mPosX; - mDimBounds.y += aY - mPosY; - mPosX = aX; - mPosY = aY; - - ResetWidgetBounds(false, true, false); -} - void nsView::ResetWidgetBounds(bool aRecurse, bool aMoveOnly, bool aInvalidateChangedSize) { if (mWindow) { diff --git a/view/src/nsView.h b/view/src/nsView.h index afbb255322d8..b76579fa1aa5 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -182,7 +182,6 @@ public: bool IsTopMost() { return((mVFlags & NS_VIEW_FLAG_TOPMOST) != 0); } void ResetWidgetBounds(bool aRecurse, bool aMoveOnly, bool aInvalidateChangedSize); - void SetPositionIgnoringChildWidgets(nscoord aX, nscoord aY); void AssertNoWindow(); void NotifyEffectiveVisibilityChanged(bool aEffectivelyVisible); diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 65318b961a53..3105310243d3 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -353,8 +353,7 @@ nsIView* nsIViewManager::GetDisplayRootFor(nsIView* aView) rendering. */ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, - const nsIntRegion& aRegion, - PRUint32 aUpdateFlags) + const nsIntRegion& aRegion) { NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch"); NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); @@ -397,7 +396,7 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, // Unset this flag first, since if aUpdateFlags includes NS_VMREFRESH_IMMEDIATE // we'll reenter this code from the UpdateAllViews call. RootViewManager()->mRecursiveRefreshPending = false; - UpdateAllViews(aUpdateFlags); + UpdateAllViews(0); } } @@ -885,8 +884,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, } if (view && aEvent->message == NS_PAINT) { - Refresh(view, event->widget, - event->region, NS_VMREFRESH_DOUBLE_BUFFER); + Refresh(view, event->widget, event->region); } } } else if (aEvent->message == NS_PAINT) { diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index 0c86d7e37a4b..541ca8acdea8 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -174,8 +174,7 @@ private: void TriggerRefresh(PRUint32 aUpdateFlags); // aView is the view for aWidget and aRegion is relative to aWidget. - void Refresh(nsView *aView, nsIWidget *aWidget, - const nsIntRegion& aRegion, PRUint32 aUpdateFlags); + void Refresh(nsView *aView, nsIWidget *aWidget, const nsIntRegion& aRegion); // aRootView is the view for aWidget, aRegion is relative to aRootView, and // aIntRegion is relative to aWidget. void RenderViews(nsView *aRootView, nsIWidget *aWidget, @@ -297,9 +296,6 @@ private: void PostInvalidateEvent(); }; -//when the refresh happens, should it be double buffered? -#define NS_VMREFRESH_DOUBLE_BUFFER 0x0001 - class nsInvalidateEvent : public nsRunnable { public: nsInvalidateEvent(class nsViewManager *vm) : mViewManager(vm) { diff --git a/xpcom/io/nsLocalFileOS2.cpp b/xpcom/io/nsLocalFileOS2.cpp index 8a108c5f6ee9..2a09bf1cb39b 100644 --- a/xpcom/io/nsLocalFileOS2.cpp +++ b/xpcom/io/nsLocalFileOS2.cpp @@ -1557,6 +1557,8 @@ nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, bool move) nsCOMPtr targetIterator; rv = target->GetDirectoryEntries(getter_AddRefs(targetIterator)); + if (NS_FAILED(rv)) + return rv; bool more; targetIterator->HasMoreElements(&more); diff --git a/xpcom/io/nsLocalFileWin.cpp b/xpcom/io/nsLocalFileWin.cpp index 41ac0ab0aa04..366272162206 100644 --- a/xpcom/io/nsLocalFileWin.cpp +++ b/xpcom/io/nsLocalFileWin.cpp @@ -1650,6 +1650,8 @@ nsLocalFile::CopyMove(nsIFile *aParentDir, const nsAString &newName, bool follow nsCOMPtr targetIterator; rv = target->GetDirectoryEntries(getter_AddRefs(targetIterator)); + if (NS_FAILED(rv)) + return rv; bool more; targetIterator->HasMoreElements(&more);