This commit is contained in:
Rob Campbell 2011-10-20 11:35:06 -04:00
Родитель 6658716924 4533393482
Коммит 81e1cddebf
150 изменённых файлов: 4988 добавлений и 4146 удалений

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

@ -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<nsISupportsPRUint8> supports =
do_CreateInstance(NS_SUPPORTS_PRUINT8_CONTRACTID);
NS_ENSURE_TRUE(supports, NS_ERROR_OUT_OF_MEMORY);

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

@ -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);

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

@ -6,7 +6,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=391728
<head>
<title>Test for Bug 391728</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/PluginUtils.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>

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

@ -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,

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

@ -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)
{ }

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

@ -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

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

@ -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

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

@ -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

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

@ -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);

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

@ -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

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

@ -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

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

@ -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() &&

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

@ -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
{

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

@ -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];

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

@ -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);

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

@ -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))

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

@ -86,7 +86,7 @@ public:
the protocol.
*/
template<class Toplevel>
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<class Toplevel>
/* 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

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

@ -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 */);
}
///////////////////////////////////////////////////////////////////////////////

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

@ -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<nsNPAPIPluginStreamListener*>(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

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

@ -106,6 +106,8 @@ public:
nsresult CreatePluginInstance(nsNPAPIPluginInstance **aResult);
nsresult Shutdown();
static nsresult RetainStream(NPStream *pstream, nsISupports **aRetainedPeer);
protected:
NPPluginFuncs mPluginFuncs;
PluginLibrary* mLibrary;

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

@ -65,7 +65,6 @@
#include "ANPBase.h"
#include <android/log.h>
#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 <map>
static std::map<void*, nsNPAPIPluginInstance*> 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<SurfaceGetter> 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)

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

@ -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
};

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

@ -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<nsNPAPIPluginInstance> 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;
}

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

@ -309,6 +309,7 @@ private:
void FixUpURLS(const nsString &name, nsAString &value);
#ifdef ANDROID
void AddPluginView(const gfxRect& aRect);
void RemovePluginView();
#endif

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

@ -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)

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

@ -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.

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

@ -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;
}

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

@ -76,6 +76,7 @@ private:
PluginInstanceParent* mNPP;
NPStream* mStream;
nsCOMPtr<nsISupports> mStreamPeer;
enum {
ALIVE,

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

@ -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

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

@ -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();

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

@ -2,7 +2,7 @@
<head>
<title>NPAPI ClearSiteData/GetSitesWithData Functionality</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/PluginUtils.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
</head>
<body>
<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>

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

@ -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<SurfaceView, SurfaceLockInfo> sSufaceMap = new HashMap<SurfaceView, SurfaceLockInfo>();
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();

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

@ -53,7 +53,7 @@ JAVAFILES = \
GeckoSurfaceView.java \
GeckoInputConnection.java \
AlertNotification.java \
SurfaceLockInfo.java \
SurfaceInfo.java \
$(NULL)
PROCESSEDJAVAFILES = \

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

@ -0,0 +1,7 @@
package org.mozilla.gecko;
public class SurfaceInfo {
public int format;
public int width;
public int height;
}

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

@ -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;
}

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

@ -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.

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

@ -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<class Other>
struct rebind {
typedef pool_allocator<Other> 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<T>& p) : allocator(p.allocator) { }
+ template <class Other>
+ pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
+ allocator = p.allocator;
+ return *this;
+ }
+
template<class Other>
- pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
+ pool_allocator(const pool_allocator<Other>& 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<size_type>(-1) / sizeof(T); }
size_type max_size(int size) const { return static_cast<size_type>(-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_

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

@ -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<T>& p) : allocator(p.allocator) { }
template <class Other>
pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
allocator = p.allocator;
return *this;
}
template<class Other>
pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
pool_allocator(const pool_allocator<Other>& 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<size_type>(-1) / sizeof(T); }
size_type max_size(int size) const { return static_cast<size_type>(-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_

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

@ -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

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

@ -172,6 +172,10 @@ CanvasLayerOGL::UpdateSurface()
}
#endif
if (mCanvasGLContext) {
mCanvasGLContext->MakeCurrent();
mCanvasGLContext->fFinish();
}
mOGLManager->MakeCurrent();
if (mCanvasGLContext &&

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

@ -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;
}

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

@ -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) {

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

@ -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<GLContextCGL>
CreateOffscreenFBOContext(const gfxIntSize& aSize,
const ContextFormat& aFormat,
CreateOffscreenFBOContext(const ContextFormat& aFormat,
bool aShare = true)
{
if (!sCGLLibrary.EnsureInitialized()) {
@ -557,23 +564,34 @@ already_AddRefed<GLContext>
GLContextProviderCGL::CreateOffscreen(const gfxIntSize& aSize,
const ContextFormat& aFormat)
{
ContextFormat actualFormat(aFormat);
actualFormat.samples = 0;
nsRefPtr<GLContextCGL> 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<GLContextCGL*>(gGlobalContext.get())->Init()) {
NS_WARNING("Couldn't init gGlobalContext.");

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

@ -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<EGLint> 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<GLContextEGL> 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<GLContextEGL> 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<GLContextEGL> 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;

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

@ -1237,9 +1237,11 @@ already_AddRefed<GLContext>
GLContextProviderGLX::CreateOffscreen(const gfxIntSize& aSize,
const ContextFormat& aFormat)
{
ContextFormat actualFormat(aFormat);
// actualFormat.samples = 0;
nsRefPtr<GLContextGLX> 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;

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

@ -259,7 +259,10 @@ GLContextProviderOSMesa::CreateOffscreen(const gfxIntSize& aSize,
return nsnull;
}
nsRefPtr<GLContextOSMesa> glContext = new GLContextOSMesa(aFormat);
ContextFormat actualFormat(aFormat);
actualFormat.samples = 0;
nsRefPtr<GLContextOSMesa> glContext = new GLContextOSMesa(actualFormat);
if (!glContext->Init(aSize))
{

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

@ -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<GLContextWGL>
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<GLContextWGL> 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();
}

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

@ -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.

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

@ -560,6 +560,7 @@ Vector<T,N,AP>::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<T,N,AP>::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() -

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

@ -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<JSScript *, 16> worklist(cx);
Vector<JSScript *, 16> 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 <INPUT> 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;
}
}

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

@ -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 *

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -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<js::Value> list;
class GCConstList {
Vector<Value> 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<JSAtom *, js::Value> ConstMap;
typedef HashMap<JSAtom *, Value> 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<js::GlobalSlotArray::Entry, 16> GlobalUseVector;
typedef Vector<GlobalSlotArray::Entry, 16> 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<uint32, 8> SlotVector;
typedef Vector<uint32, 8> 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<JSCodeGenerator *>(this);
return static_cast<CodeGenerator *>(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__ */

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

@ -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 */

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

@ -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__ */

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

@ -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);

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

@ -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_<AtomDeclNode>(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)

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

@ -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 <class Map>
@ -152,7 +154,7 @@ struct AtomThingMapPtr
struct AtomDefnMapPtr : public AtomThingMapPtr<AtomDefnMap>
{
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<AtomIndexMapPtr> 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;

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

@ -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();

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

@ -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_<JSParseNode>();
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_<ParseNode>(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_<BinaryNode>(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_<ParseNode>(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_<ParseNode>(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_<BinaryNode>(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;

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

@ -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
* ----- ------- -------
* <Definitions>
* 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 <?target data?> */
PropertyName *target; /* target in <?target data?> */
JSAtom *data; /* data (or null) in <?target data?> */
} 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__ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -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__ */

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

@ -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;
}

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

@ -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__ */

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

@ -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;

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

@ -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

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

@ -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.

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

@ -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)

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

@ -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 */

61
js/src/jsboolinlines.h Normal file
Просмотреть файл

@ -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 <jwalden+code@mit.edu> (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___ */

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

@ -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;

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

@ -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;
}
}

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

@ -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);

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

@ -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) {

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

@ -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;

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

@ -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)

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

@ -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___ */

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

@ -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, &regs.sp[-1], false))
if (!obj->deleteProperty(cx, atom->asPropertyName(), &regs.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, &regs.sp[-2], script->strictModeCode))
if (!obj->deleteGeneric(cx, id, &regs.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, &regs.sp[-1], script->strictModeCode))
if (!obj->setGeneric(cx, id, &regs.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, &regs.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<Shape *>(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;

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

@ -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)

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

@ -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

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

@ -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;

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

@ -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

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

@ -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);
}

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

@ -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

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

@ -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

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

@ -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;
}

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

@ -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<JSAtom *, JSDefinition *, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
typedef Vector<UpvarCookie, 8> UpvarCookies;

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

@ -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;

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

@ -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;

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

@ -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
/*

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

@ -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;

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

@ -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<TraceMonitor *> 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<TraceMonitor *> 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<TraceMonitor *> 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<TraceMonitor *> 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<TraceMonitor *> 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,

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

@ -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,

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

@ -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))

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

@ -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);

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

@ -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

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

@ -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 *

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

@ -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);

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

@ -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);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше