зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c, a=merge
This commit is contained in:
Коммит
4ae95aae6b
|
@ -53,7 +53,8 @@ function getStringPref(pref, def) {
|
|||
}
|
||||
|
||||
function log(str) {
|
||||
dump(str + '\n');
|
||||
var msg = 'ShumwayBootstrapUtils.jsm: ' + str;
|
||||
Services.console.logStringMessage(msg);
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a factory.
|
||||
|
@ -80,6 +81,19 @@ Factory.prototype = {
|
|||
let converterFactory = new Factory();
|
||||
let overlayConverterFactory = new Factory();
|
||||
|
||||
function allowedPlatformForMedia() {
|
||||
var oscpu = Cc["@mozilla.org/network/protocol;1?name=http"]
|
||||
.getService(Ci.nsIHttpProtocolHandler).oscpu;
|
||||
if (oscpu.indexOf('Windows NT') === 0) {
|
||||
return oscpu.indexOf('Windows NT 5') < 0; // excluding Windows XP
|
||||
}
|
||||
if (oscpu.indexOf('Intel Mac OS X') === 0) {
|
||||
return true;
|
||||
}
|
||||
// Other platforms are not supported yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
var ShumwayBootstrapUtils = {
|
||||
register: function () {
|
||||
// Register the components.
|
||||
|
@ -89,6 +103,14 @@ var ShumwayBootstrapUtils = {
|
|||
if (registerOverlayPreview) {
|
||||
var ignoreCTP = getBoolPref(PREF_IGNORE_CTP, true);
|
||||
var whitelist = getStringPref(PREF_WHITELIST);
|
||||
// Some platforms cannot support video playback, and our whitelist targets
|
||||
// only video players atm. We need to disable Shumway for those platforms.
|
||||
if (whitelist && !Services.prefs.prefHasUserValue(PREF_WHITELIST) &&
|
||||
!allowedPlatformForMedia()) {
|
||||
log('Default SWF whitelist is used on an unsupported platform -- ' +
|
||||
'using demo whitelist.');
|
||||
whitelist = 'http://www.areweflashyet.com/*.swf';
|
||||
}
|
||||
Ph.registerPlayPreviewMimeType(SWF_CONTENT_TYPE, ignoreCTP,
|
||||
undefined, whitelist);
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ function isShumwayEnabledFor(actions) {
|
|||
function getVersionInfo() {
|
||||
var deferred = Promise.defer();
|
||||
var versionInfo = {
|
||||
version: 'unknown',
|
||||
geckoVersion: 'unknown',
|
||||
geckoBuildID: 'unknown',
|
||||
shumwayVersion: 'unknown'
|
||||
};
|
||||
|
@ -230,18 +230,30 @@ function getVersionInfo() {
|
|||
versionInfo.geckoVersion = appInfo.version;
|
||||
versionInfo.geckoBuildID = appInfo.appBuildID;
|
||||
} catch (e) {
|
||||
log('Error encountered while getting platform version info:', e);
|
||||
log('Error encountered while getting platform version info: ' + e);
|
||||
}
|
||||
var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open('GET', 'resource://shumway/version.txt', true);
|
||||
xhr.overrideMimeType('text/plain');
|
||||
xhr.onload = function () {
|
||||
try {
|
||||
var addonId = "shumway@research.mozilla.org";
|
||||
AddonManager.getAddonByID(addonId, function(addon) {
|
||||
versionInfo.shumwayVersion = addon ? addon.version : 'n/a';
|
||||
deferred.resolve(versionInfo);
|
||||
});
|
||||
// Trying to merge version.txt lines into something like:
|
||||
// "version (sha) details"
|
||||
var lines = xhr.responseText.split(/\n/g);
|
||||
lines[1] = '(' + lines[1] + ')';
|
||||
versionInfo.shumwayVersion = lines.join(' ');
|
||||
} catch (e) {
|
||||
log('Error encountered while getting Shumway version info:', e);
|
||||
deferred.resolve(versionInfo);
|
||||
log('Error while parsing version info: ' + e);
|
||||
}
|
||||
deferred.resolve(versionInfo);
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
log('Error while reading version info: ' + xhr.error);
|
||||
deferred.resolve(versionInfo);
|
||||
};
|
||||
xhr.send();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
@ -754,6 +766,7 @@ function activateShumwayScripts(window, requestListener) {
|
|||
}
|
||||
|
||||
function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
|
||||
var traceExternalInterface = getBoolPref('shumway.externalInterface.trace', false);
|
||||
if (!wrappedWindow.__flash__initialized) {
|
||||
wrappedWindow.__flash__initialized = true;
|
||||
wrappedWindow.__flash__toXML = function __flash__toXML(obj) {
|
||||
|
@ -786,29 +799,32 @@ function initExternalCom(wrappedWindow, wrappedObject, targetWindow) {
|
|||
}
|
||||
};
|
||||
wrappedWindow.__flash__eval = function (expr) {
|
||||
this.console.log('__flash__eval: ' + expr);
|
||||
traceExternalInterface && this.console.log('__flash__eval: ' + expr);
|
||||
// allowScriptAccess protects page from unwanted swf scripts,
|
||||
// we can execute script in the page context without restrictions.
|
||||
return this.eval(expr);
|
||||
var result = this.eval(expr);
|
||||
traceExternalInterface && this.console.log('__flash__eval (result): ' + result);
|
||||
return result;
|
||||
}.bind(wrappedWindow);
|
||||
wrappedWindow.__flash__call = function (expr) {
|
||||
this.console.log('__flash__call (ignored): ' + expr);
|
||||
traceExternalInterface && this.console.log('__flash__call (ignored): ' + expr);
|
||||
};
|
||||
}
|
||||
wrappedObject.__flash__registerCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__registerCallback: ' + functionName);
|
||||
Components.utils.exportFunction(function () {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
wrappedWindow.console.log('__flash__callIn: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__callIn: ' + functionName);
|
||||
var result;
|
||||
if (targetWindow.wrappedJSObject.onExternalCallback) {
|
||||
result = targetWindow.wrappedJSObject.onExternalCallback({functionName: functionName, args: args});
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__callIn (result): ' + result);
|
||||
}
|
||||
return wrappedWindow.eval(result);
|
||||
}, this, { defineAs: functionName });
|
||||
};
|
||||
wrappedObject.__flash__unregisterCallback = function (functionName) {
|
||||
wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
|
||||
traceExternalInterface && wrappedWindow.console.log('__flash__unregisterCallback: ' + functionName);
|
||||
delete this[functionName];
|
||||
};
|
||||
}
|
||||
|
@ -909,7 +925,11 @@ ShumwayStreamConverterBase.prototype = {
|
|||
throw new Error('Movie url is not specified');
|
||||
}
|
||||
|
||||
baseUrl = objectParams.base || pageUrl;
|
||||
if (objectParams.base) {
|
||||
baseUrl = Services.io.newURI(objectParams.base, null, pageUrl).spec;
|
||||
} else {
|
||||
baseUrl = pageUrl;
|
||||
}
|
||||
|
||||
var movieParams = {};
|
||||
if (objectParams.flashvars) {
|
||||
|
|
|
@ -17,6 +17,7 @@ var EXPORTED_SYMBOLS = ["ShumwayUtils"];
|
|||
|
||||
const PREF_PREFIX = 'shumway.';
|
||||
const PREF_DISABLED = PREF_PREFIX + 'disabled';
|
||||
const PREF_WHITELIST = PREF_PREFIX + 'swf.whitelist';
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
|
@ -43,6 +44,7 @@ let ShumwayUtils = {
|
|||
_registered: false,
|
||||
|
||||
init: function init() {
|
||||
this.migratePreferences();
|
||||
if (this.enabled)
|
||||
this._ensureRegistered();
|
||||
else
|
||||
|
@ -56,6 +58,19 @@ let ShumwayUtils = {
|
|||
Services.prefs.addObserver(PREF_DISABLED, this, false);
|
||||
},
|
||||
|
||||
migratePreferences: function migratePreferences() {
|
||||
// At one point we had shumway.disabled set to true by default,
|
||||
// and we are trying to replace it with shumway.swf.whitelist:
|
||||
// checking if the user already changed it before to reset
|
||||
// the whitelist to '*'.
|
||||
if (Services.prefs.prefHasUserValue(PREF_DISABLED) &&
|
||||
!Services.prefs.prefHasUserValue(PREF_WHITELIST) &&
|
||||
!getBoolPref(PREF_DISABLED, false)) {
|
||||
// The user is already using Shumway -- enabling all web sites.
|
||||
Services.prefs.setCharPref(PREF_WHITELIST, '*');
|
||||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (this.enabled)
|
||||
|
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,2 +1,2 @@
|
|||
0.9.3693
|
||||
217e2e2
|
||||
0.9.3775
|
||||
a82ac47
|
||||
|
|
|
@ -111,7 +111,7 @@ limitations under the License.
|
|||
<menuitem label="Open in Inspector" id="inspectorMenu"></menuitem>
|
||||
<menuitem label="Report Problems" id="reportMenu"></menuitem>
|
||||
<menuitem label="Reload in Adobe Flash Player" id="fallbackMenu" hidden></menuitem>
|
||||
<menuitem label="About Shumway" id="aboutMenu"></menuitem>
|
||||
<menuitem label="About Shumway %version%..." id="aboutMenu"></menuitem>
|
||||
</menu>
|
||||
</section>
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ function runViewer() {
|
|||
document.getElementById('inspectorMenu').addEventListener('click', showInInspector);
|
||||
document.getElementById('reportMenu').addEventListener('click', reportIssue);
|
||||
document.getElementById('aboutMenu').addEventListener('click', showAbout);
|
||||
|
||||
var version = Shumway.version || '';
|
||||
document.getElementById('aboutMenu').label =
|
||||
document.getElementById('aboutMenu').label.replace('%version%', version);
|
||||
}
|
||||
|
||||
function showURL() {
|
||||
|
|
|
@ -44,7 +44,7 @@ function runSwfPlayer(flashParams) {
|
|||
Shumway.AVM2.Verifier.enabled.value = compilerSettings.verifier;
|
||||
|
||||
Shumway.createAVM2(builtinPath, viewerPlayerglobalInfo, sysMode, appMode, function (avm2) {
|
||||
function runSWF(file) {
|
||||
function runSWF(file, buffer, baseUrl) {
|
||||
var player = new Shumway.Player.Window.WindowPlayer(window, window.parent);
|
||||
player.defaultStageColor = flashParams.bgcolor;
|
||||
player.movieParams = flashParams.movieParams;
|
||||
|
@ -54,17 +54,18 @@ function runSwfPlayer(flashParams) {
|
|||
|
||||
Shumway.ExternalInterfaceService.instance = player.createExternalInterfaceService();
|
||||
|
||||
player.load(file);
|
||||
player.pageUrl = baseUrl;
|
||||
player.load(file, buffer);
|
||||
}
|
||||
Shumway.FileLoadingService.instance.setBaseUrl(baseUrl);
|
||||
if (asyncLoading) {
|
||||
runSWF(movieUrl);
|
||||
runSWF(movieUrl, undefined, baseUrl);
|
||||
} else {
|
||||
new Shumway.BinaryFileReader(movieUrl).readAll(null, function(buffer, error) {
|
||||
if (!buffer) {
|
||||
throw "Unable to open the file " + movieUrl + ": " + error;
|
||||
}
|
||||
runSWF(movieUrl, buffer);
|
||||
runSWF(movieUrl, buffer, baseUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -127,6 +128,11 @@ function setupServices() {
|
|||
this.onprogress && this.onprogress(args.array, {bytesLoaded: args.loaded, bytesTotal: args.total});
|
||||
break;
|
||||
}
|
||||
},
|
||||
close: function () {
|
||||
if (Shumway.FileLoadingService.instance.sessions[sessionId]) {
|
||||
// TODO send abort
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
|
|
@ -1811,22 +1811,30 @@ ContentChild::ProcessingError(Result aCode, const char* aReason)
|
|||
case MsgDropped:
|
||||
NS_WARNING("MsgDropped in ContentChild");
|
||||
return;
|
||||
|
||||
case MsgNotKnown:
|
||||
NS_RUNTIMEABORT("aborting because of MsgNotKnown");
|
||||
case MsgNotAllowed:
|
||||
NS_RUNTIMEABORT("aborting because of MsgNotAllowed");
|
||||
case MsgPayloadError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgPayloadError");
|
||||
case MsgProcessingError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgProcessingError");
|
||||
case MsgRouteError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgRouteError");
|
||||
case MsgValueError:
|
||||
NS_RUNTIMEABORT("aborting because of MsgValueError");
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
}
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
|
||||
if (ManagedPCrashReporterChild().Length() > 0) {
|
||||
CrashReporterChild* crashReporter =
|
||||
static_cast<CrashReporterChild*>(ManagedPCrashReporterChild()[0]);
|
||||
nsDependentCString reason(aReason);
|
||||
crashReporter->SendAnnotateCrashReport(
|
||||
NS_LITERAL_CSTRING("ipc_channel_error"),
|
||||
reason);
|
||||
}
|
||||
#endif
|
||||
NS_RUNTIMEABORT("Content child abort due to IPC error");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -497,10 +497,10 @@ SystemMessageInternal.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Return the |msg| of each pending message (drop the |msgID|).
|
||||
// Return the |msg| of each pending message.
|
||||
let pendingMessages = [];
|
||||
page.pendingMessages.forEach(function(aMessage) {
|
||||
pendingMessages.push(aMessage.msg);
|
||||
pendingMessages.push({ msg: aMessage.msg, msgID: aMessage.msgID });
|
||||
});
|
||||
|
||||
// Clear the pending queue for this page. This is OK since we'll store
|
||||
|
|
|
@ -267,7 +267,7 @@ SystemMessageManager.prototype = {
|
|||
}
|
||||
|
||||
let messages = (aMessage.name == "SystemMessageManager:Message")
|
||||
? [msg.msg]
|
||||
? [{ msg: msg.msg, msgID: msg.msgID }]
|
||||
: msg.msgQueue;
|
||||
|
||||
// We only dispatch messages when a handler is registered.
|
||||
|
@ -285,7 +285,7 @@ SystemMessageManager.prototype = {
|
|||
}
|
||||
|
||||
messages.forEach(function(aMsg) {
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg, msg.msgID);
|
||||
this._dispatchMessage(msg.type, dispatcher, aMsg.msg, aMsg.msgID);
|
||||
}, this);
|
||||
|
||||
} else {
|
||||
|
|
|
@ -535,13 +535,13 @@ TryEnablingJit(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t
|
|||
// BaselineScript, so if those checks hold now they must hold at least until
|
||||
// the BaselineScript is discarded and when that happens the FFI exit is
|
||||
// patched back.
|
||||
if (!types::TypeScript::ThisTypes(script)->hasType(types::Type::UndefinedType()))
|
||||
if (!TypeScript::ThisTypes(script)->hasType(TypeSet::UndefinedType()))
|
||||
return true;
|
||||
for (uint32_t i = 0; i < fun->nargs(); i++) {
|
||||
types::StackTypeSet *typeset = types::TypeScript::ArgTypes(script, i);
|
||||
types::Type type = types::Type::DoubleType();
|
||||
StackTypeSet *typeset = TypeScript::ArgTypes(script, i);
|
||||
TypeSet::Type type = TypeSet::DoubleType();
|
||||
if (!argv[i].isDouble())
|
||||
type = types::Type::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
type = TypeSet::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
if (!typeset->hasType(type))
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "vm/Shape-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using js::frontend::IsIdentifier;
|
||||
using mozilla::ArrayLength;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::Maybe;
|
||||
|
|
|
@ -2729,7 +2729,7 @@ js::StoreReference##T::Func(JSContext *cx, unsigned argc, Value *vp) \
|
|||
int32_t offset = args[1].toInt32(); \
|
||||
\
|
||||
jsid id = args[2].isString() \
|
||||
? types::IdToTypeId(AtomToId(&args[2].toString()->asAtom())) \
|
||||
? IdToTypeId(AtomToId(&args[2].toString()->asAtom())) \
|
||||
: JSID_VOID; \
|
||||
\
|
||||
/* Should be guaranteed by the typed objects API: */ \
|
||||
|
@ -2795,8 +2795,8 @@ StoreReferenceHeapValue::store(JSContext *cx, HeapValue *heap, const Value &v,
|
|||
// considered to contain undefined.
|
||||
if (!v.isUndefined()) {
|
||||
if (cx->isJSContext())
|
||||
types::AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!types::HasTypePropertyId(obj, id, v))
|
||||
AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!HasTypePropertyId(obj, id, v))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2815,8 +2815,8 @@ StoreReferenceHeapPtrObject::store(JSContext *cx, HeapPtrObject *heap, const Val
|
|||
// considered to contain null.
|
||||
if (v.isObject()) {
|
||||
if (cx->isJSContext())
|
||||
types::AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!types::HasTypePropertyId(obj, id, v))
|
||||
AddTypePropertyId(cx->asJSContext(), obj, id, v);
|
||||
else if (!HasTypePropertyId(obj, id, v))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1902,7 +1902,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* has no object to stand in the static scope chain, 2. to minimize memory
|
||||
* bloat where a single live function keeps its whole global script
|
||||
* alive.), ScopeCoordinateToTypeSet is not able to find the var/let's
|
||||
* associated types::TypeSet.
|
||||
* associated TypeSet.
|
||||
*/
|
||||
if (skip) {
|
||||
BytecodeEmitter *bceSkipped = bce;
|
||||
|
@ -3704,7 +3704,7 @@ EmitDestructuringOpsObjectHelper(ExclusiveContext *cx, BytecodeEmitter *bce, Par
|
|||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != types::IdToTypeId(id)) {
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!EmitTree(cx, bce, key)) // ... OBJ OBJ KEY
|
||||
return false;
|
||||
} else {
|
||||
|
@ -6622,7 +6622,7 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
jsid id = NameToId(key->pn_atom->asPropertyName());
|
||||
if (id != types::IdToTypeId(id)) {
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!EmitTree(cx, bce, key))
|
||||
return false;
|
||||
isIndex = true;
|
||||
|
|
|
@ -834,7 +834,7 @@ Fold(ExclusiveContext *cx, ParseNode **pnp,
|
|||
}
|
||||
}
|
||||
|
||||
if (name && NameToId(name) == types::IdToTypeId(NameToId(name))) {
|
||||
if (name && NameToId(name) == IdToTypeId(NameToId(name))) {
|
||||
// Optimization 3: We have pn1["foo"] where foo is not an index.
|
||||
// Convert to a property access (like pn1.foo) which we optimize
|
||||
// better downstream. Don't bother with this for names which TI
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
JS_STATIC_ASSERT(AllocKinds == FINALIZE_LIMIT);
|
||||
JS_STATIC_ASSERT(LastObjectAllocKind == FINALIZE_OBJECT_LAST);
|
||||
|
|
|
@ -787,18 +787,18 @@ gc::MarkValueRoot(JSTracer *trc, Value *v, const char *name)
|
|||
}
|
||||
|
||||
void
|
||||
gc::MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name)
|
||||
TypeSet::MarkTypeRoot(JSTracer *trc, TypeSet::Type *v, const char *name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
trc->setTracingName(name);
|
||||
if (v->isSingleton()) {
|
||||
JSObject *obj = v->singleton();
|
||||
MarkInternal(trc, &obj);
|
||||
*v = types::Type::ObjectType(obj);
|
||||
*v = TypeSet::ObjectType(obj);
|
||||
} else if (v->isGroup()) {
|
||||
ObjectGroup *group = v->group();
|
||||
MarkInternal(trc, &group);
|
||||
*v = types::Type::ObjectType(group);
|
||||
*v = TypeSet::ObjectType(group);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1426,7 +1426,7 @@ ScanObjectGroup(GCMarker *gcmarker, ObjectGroup *group)
|
|||
{
|
||||
unsigned count = group->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (types::Property *prop = group->getProperty(i))
|
||||
if (ObjectGroup::Property *prop = group->getProperty(i))
|
||||
MarkId(gcmarker, &prop->id, "ObjectGroup property id");
|
||||
}
|
||||
|
||||
|
@ -1454,8 +1454,7 @@ gc::MarkChildren(JSTracer *trc, ObjectGroup *group)
|
|||
{
|
||||
unsigned count = group->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
types::Property *prop = group->getProperty(i);
|
||||
if (prop)
|
||||
if (ObjectGroup::Property *prop = group->getProperty(i))
|
||||
MarkId(trc, &prop->id, "group_property");
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,6 @@ struct IonScript;
|
|||
struct VMFunction;
|
||||
}
|
||||
|
||||
namespace types {
|
||||
class Type;
|
||||
}
|
||||
|
||||
namespace gc {
|
||||
|
||||
/*** Object Marking ***/
|
||||
|
@ -213,9 +209,6 @@ MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
|
|||
MarkValueRootRange(trc, end - begin, begin, name);
|
||||
}
|
||||
|
||||
void
|
||||
MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name);
|
||||
|
||||
bool
|
||||
IsValueMarked(Value *v);
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ MarkExactStackRootsAcrossTypes(T context, JSTracer *trc)
|
|||
MarkExactStackRootList<LazyScript *, MarkLazyScriptRoot>(trc, context, "exact-lazy-script");
|
||||
MarkExactStackRootList<jsid, MarkIdRoot>(trc, context, "exact-id");
|
||||
MarkExactStackRootList<Value, MarkValueRoot>(trc, context, "exact-value");
|
||||
MarkExactStackRootList<types::Type, MarkTypeRoot>(trc, context, "types::Type");
|
||||
MarkExactStackRootList<TypeSet::Type, TypeSet::MarkTypeRoot>(trc, context, "TypeSet::Type");
|
||||
MarkExactStackRootList<Bindings, MarkBindingsRoot>(trc, context, "Bindings");
|
||||
MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
|
||||
trc, context, "JSPropertyDescriptor");
|
||||
|
|
|
@ -115,7 +115,7 @@ Zone::beginSweepTypes(FreeOp *fop, bool releaseTypes)
|
|||
if (active)
|
||||
releaseTypes = false;
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(this);
|
||||
AutoClearTypeInferenceStateOnOOM oom(this);
|
||||
types.beginSweep(fop, releaseTypes, oom);
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ struct Zone : public JS::shadow::Zone,
|
|||
public:
|
||||
js::gc::ArenaLists arenas;
|
||||
|
||||
js::types::TypeZone types;
|
||||
js::TypeZone types;
|
||||
|
||||
// The set of compartments in this zone.
|
||||
typedef js::Vector<JSCompartment *, 1, js::SystemAllocPolicy> CompartmentVector;
|
||||
|
|
|
@ -90,7 +90,7 @@ BaselineCompiler::compile()
|
|||
return Method_Error;
|
||||
|
||||
// Pin analysis info during compilation.
|
||||
types::AutoEnterAnalysis autoEnterAnalysis(cx);
|
||||
AutoEnterAnalysis autoEnterAnalysis(cx);
|
||||
|
||||
MOZ_ASSERT(!script->hasBaselineScript());
|
||||
|
||||
|
@ -250,7 +250,7 @@ BaselineCompiler::compile()
|
|||
#endif
|
||||
|
||||
uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
|
||||
types::FillBytecodeTypeMap(script, bytecodeMap);
|
||||
FillBytecodeTypeMap(script, bytecodeMap);
|
||||
|
||||
// The last entry in the last index found, and is used to avoid binary
|
||||
// searches for the sought entry when queries are in linear order.
|
||||
|
|
|
@ -771,7 +771,7 @@ CloneOldBaselineStub(JSContext *cx, DebugModeOSREntryVector &entries, size_t ent
|
|||
static bool
|
||||
InvalidateScriptsInZone(JSContext *cx, Zone *zone, const Vector<DebugModeOSREntry> &entries)
|
||||
{
|
||||
types::RecompileInfoVector invalid;
|
||||
RecompileInfoVector invalid;
|
||||
for (UniqueScriptOSREntryIter iter(entries); !iter.done(); ++iter) {
|
||||
JSScript *script = iter.entry().script;
|
||||
if (script->compartment()->zone() != zone)
|
||||
|
|
|
@ -1197,12 +1197,12 @@ DoTypeMonitorFallback(JSContext *cx, BaselineFrame *frame, ICTypeMonitor_Fallbac
|
|||
uint32_t argument;
|
||||
if (stub->monitorsThis()) {
|
||||
MOZ_ASSERT(pc == script->code());
|
||||
types::TypeScript::SetThis(cx, script, value);
|
||||
TypeScript::SetThis(cx, script, value);
|
||||
} else if (stub->monitorsArgument(&argument)) {
|
||||
MOZ_ASSERT(pc == script->code());
|
||||
types::TypeScript::SetArgument(cx, script, argument, value);
|
||||
TypeScript::SetArgument(cx, script, argument, value);
|
||||
} else {
|
||||
types::TypeScript::Monitor(cx, script, pc, value);
|
||||
TypeScript::Monitor(cx, script, pc, value);
|
||||
}
|
||||
|
||||
if (!stub->addMonitorStubForValue(cx, script, value))
|
||||
|
@ -1324,12 +1324,12 @@ ICUpdatedStub::addUpdateStubForValue(JSContext *cx, HandleScript script, HandleO
|
|||
return true;
|
||||
}
|
||||
|
||||
types::EnsureTrackPropertyTypes(cx, obj, id);
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
|
||||
// Make sure that undefined values are explicitly included in the property
|
||||
// types for an object if generating a stub to write an undefined value.
|
||||
if (val.isUndefined() && types::CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
types::AddTypePropertyId(cx, obj, id, val);
|
||||
if (val.isUndefined() && CanHaveEmptyPropertyTypesForOwnProperty(obj))
|
||||
AddTypePropertyId(cx, obj, id, val);
|
||||
|
||||
if (val.isPrimitive()) {
|
||||
JSValueType type = val.isDouble() ? JSVAL_TYPE_DOUBLE : val.extractNonDoubleType();
|
||||
|
@ -1423,7 +1423,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
|||
case ICStub::SetElem_DenseAdd: {
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
id = JSID_VOID;
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
break;
|
||||
}
|
||||
case ICStub::SetProp_Native:
|
||||
|
@ -1435,7 +1435,7 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
|||
id = NameToId(ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc));
|
||||
else
|
||||
id = NameToId(script->getName(pc));
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
break;
|
||||
}
|
||||
case ICStub::SetProp_TypedObject: {
|
||||
|
@ -1448,12 +1448,12 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H
|
|||
// and non-object non-null values will cause the stub to fail to
|
||||
// match shortly and we will end up doing the assignment in the VM.
|
||||
if (value.isObject())
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
} else {
|
||||
// Ignore undefined values, which are included implicitly in type
|
||||
// information for this property.
|
||||
if (!value.isUndefined())
|
||||
types::AddTypePropertyId(cx, obj, id, value);
|
||||
AddTypePropertyId(cx, obj, id, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3975,13 +3975,13 @@ DoGetElemFallback(JSContext *cx, BaselineFrame *frame, ICGetElem_Fallback *stub_
|
|||
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
|
||||
return false;
|
||||
if (isOptimizedArgs)
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
}
|
||||
|
||||
if (!isOptimizedArgs) {
|
||||
if (!GetElementOperation(cx, op, &lhsCopy, rhs, res))
|
||||
return false;
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
}
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
|
@ -5803,7 +5803,7 @@ TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
|
||||
// Instantiate this global property, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, current, id);
|
||||
EnsureTrackPropertyTypes(cx, current, id);
|
||||
|
||||
if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
|
||||
|
@ -6006,7 +6006,7 @@ DoGetNameFallback(JSContext *cx, BaselineFrame *frame, ICGetName_Fallback *stub_
|
|||
return false;
|
||||
}
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
|
@ -6195,7 +6195,7 @@ DoGetIntrinsicFallback(JSContext *cx, BaselineFrame *frame, ICGetIntrinsic_Fallb
|
|||
// needs to be monitored once. Attach a stub to load the resulting constant
|
||||
// directly.
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
|
@ -6383,7 +6383,7 @@ HasUnanalyzedNewScript(JSObject *obj)
|
|||
if (obj->isSingleton())
|
||||
return false;
|
||||
|
||||
types::TypeNewScript *newScript = obj->group()->newScript();
|
||||
TypeNewScript *newScript = obj->group()->newScript();
|
||||
if (newScript && !newScript->analyzed())
|
||||
return true;
|
||||
|
||||
|
@ -6451,7 +6451,7 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
|
||||
// Instantiate this property for singleton holders, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, holder, NameToId(name));
|
||||
EnsureTrackPropertyTypes(cx, holder, NameToId(name));
|
||||
|
||||
ICStub::Kind kind;
|
||||
if (obj == holder)
|
||||
|
@ -6741,7 +6741,7 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
|
|||
// Instantiate this property, for use during Ion compilation.
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, proto, id);
|
||||
EnsureTrackPropertyTypes(cx, proto, id);
|
||||
|
||||
// For now, only look for properties directly set on the prototype.
|
||||
RootedShape shape(cx, proto->lookup(cx, id));
|
||||
|
@ -6869,7 +6869,7 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_
|
|||
if (!ComputeGetPropResult(cx, frame, op, name, val, res))
|
||||
return false;
|
||||
|
||||
types::TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
TypeScript::Monitor(cx, frame->script(), pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
|
@ -8054,8 +8054,8 @@ TryAttachSetValuePropStub(JSContext *cx, HandleScript script, jsbytecode *pc, IC
|
|||
// properties, TI will not mark the property as having been
|
||||
// overwritten. Don't attach a stub in this case, so that we don't
|
||||
// execute another write to the property without TI seeing that write.
|
||||
types::EnsureTrackPropertyTypes(cx, obj, id);
|
||||
if (!types::PropertyHasBeenMarkedNonConstant(obj, id)) {
|
||||
EnsureTrackPropertyTypes(cx, obj, id);
|
||||
if (!PropertyHasBeenMarkedNonConstant(obj, id)) {
|
||||
*attached = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -9327,7 +9327,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
|||
// Keep track of the function's |prototype| property in type
|
||||
// information, for use during Ion compilation.
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
|
||||
EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
|
||||
|
||||
// Remember the template object associated with any script being called
|
||||
// as a constructor, for later use during Ion compilation.
|
||||
|
@ -9345,7 +9345,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
|||
// stub. After the analysis is performed, CreateThisForFunction may
|
||||
// start returning objects with a different type, and the Ion
|
||||
// compiler might get confused.
|
||||
types::TypeNewScript *newScript = templateObject->group()->newScript();
|
||||
TypeNewScript *newScript = templateObject->group()->newScript();
|
||||
if (newScript && !newScript->analyzed()) {
|
||||
// Clear the object just created from the preliminary objects
|
||||
// on the TypeNewScript, as it will not be used or filled in by
|
||||
|
@ -9573,7 +9573,7 @@ DoCallFallback(JSContext *cx, BaselineFrame *frame, ICCall_Fallback *stub_, uint
|
|||
return false;
|
||||
}
|
||||
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
|
||||
// Check if debug mode toggling made the stub invalid.
|
||||
if (stub.invalid())
|
||||
|
@ -11234,7 +11234,7 @@ DoInstanceOfFallback(JSContext *cx, BaselineFrame *frame, ICInstanceOf_Fallback
|
|||
|
||||
// For functions, keep track of the |prototype| property in type information,
|
||||
// for use during Ion compilation.
|
||||
types::EnsureTrackPropertyTypes(cx, obj, NameToId(cx->names().prototype));
|
||||
EnsureTrackPropertyTypes(cx, obj, NameToId(cx->names().prototype));
|
||||
|
||||
if (stub->numOptimizedStubs() >= ICInstanceOf_Fallback::MAX_OPTIMIZED_STUBS)
|
||||
return true;
|
||||
|
|
|
@ -3395,7 +3395,7 @@ CodeGenerator::generateArgumentsChecks(bool bailout)
|
|||
for (uint32_t i = info.startArgSlot(); i < info.endArgSlot(); i++) {
|
||||
// All initial parameters are guaranteed to be MParameters.
|
||||
MParameter *param = rp->getOperand(i)->toParameter();
|
||||
const types::TypeSet *types = param->resultTypeSet();
|
||||
const TypeSet *types = param->resultTypeSet();
|
||||
if (!types || types->unknown())
|
||||
continue;
|
||||
|
||||
|
@ -7215,11 +7215,11 @@ CodeGenerator::generate()
|
|||
struct AutoDiscardIonCode
|
||||
{
|
||||
JSContext *cx;
|
||||
types::RecompileInfo *recompileInfo;
|
||||
RecompileInfo *recompileInfo;
|
||||
IonScript *ionScript;
|
||||
bool keep;
|
||||
|
||||
AutoDiscardIonCode(JSContext *cx, types::RecompileInfo *recompileInfo)
|
||||
AutoDiscardIonCode(JSContext *cx, RecompileInfo *recompileInfo)
|
||||
: cx(cx), recompileInfo(recompileInfo), ionScript(nullptr), keep(false) {}
|
||||
|
||||
~AutoDiscardIonCode() {
|
||||
|
@ -7240,7 +7240,7 @@ struct AutoDiscardIonCode
|
|||
};
|
||||
|
||||
bool
|
||||
CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
|
||||
CodeGenerator::link(JSContext *cx, CompilerConstraintList *constraints)
|
||||
{
|
||||
RootedScript script(cx, gen->info().script());
|
||||
OptimizationLevel optimizationLevel = gen->optimizationInfo().level();
|
||||
|
@ -7261,8 +7261,8 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
|
|||
// Check to make sure we didn't have a mid-build invalidation. If so, we
|
||||
// will trickle to jit::Compile() and return Method_Skipped.
|
||||
uint32_t warmUpCount = script->getWarmUpCount();
|
||||
types::RecompileInfo recompileInfo;
|
||||
if (!types::FinishCompilation(cx, script, constraints, &recompileInfo))
|
||||
RecompileInfo recompileInfo;
|
||||
if (!FinishCompilation(cx, script, constraints, &recompileInfo))
|
||||
return true;
|
||||
|
||||
// IonMonkey could have inferred better type information during
|
||||
|
|
|
@ -56,7 +56,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
public:
|
||||
bool generate();
|
||||
bool generateAsmJS(AsmJSFunctionLabels *labels);
|
||||
bool link(JSContext *cx, types::CompilerConstraintList *constraints);
|
||||
bool link(JSContext *cx, CompilerConstraintList *constraints);
|
||||
|
||||
void visitLabel(LLabel *lir);
|
||||
void visitNop(LNop *lir);
|
||||
|
|
|
@ -471,7 +471,7 @@ jit::LazyLinkTopActivation(JSContext *cx)
|
|||
IonBuilder *builder = it.script()->ionScript()->pendingBuilder();
|
||||
it.script()->setPendingIonBuilder(cx, nullptr);
|
||||
|
||||
types::AutoEnterAnalysis enterTypes(cx);
|
||||
AutoEnterAnalysis enterTypes(cx);
|
||||
RootedScript script(cx, builder->script());
|
||||
|
||||
// Remove from pending.
|
||||
|
@ -749,7 +749,7 @@ IonScript::IonScript()
|
|||
}
|
||||
|
||||
IonScript *
|
||||
IonScript::New(JSContext *cx, types::RecompileInfo recompileInfo,
|
||||
IonScript::New(JSContext *cx, RecompileInfo recompileInfo,
|
||||
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
|
||||
size_t snapshotsListSize, size_t snapshotsRVATableSize,
|
||||
size_t recoversSize, size_t bailoutEntries,
|
||||
|
@ -1600,7 +1600,7 @@ AttachFinishedCompilations(JSContext *cx)
|
|||
if (!ion)
|
||||
return;
|
||||
|
||||
types::AutoEnterAnalysis enterTypes(cx);
|
||||
AutoEnterAnalysis enterTypes(cx);
|
||||
AutoLockHelperThreadState lock;
|
||||
|
||||
GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
|
||||
|
@ -1758,7 +1758,7 @@ TrackAllProperties(JSContext *cx, JSObject *obj)
|
|||
MOZ_ASSERT(obj->isSingleton());
|
||||
|
||||
for (Shape::Range<NoGC> range(obj->lastProperty()); !range.empty(); range.popFront())
|
||||
types::EnsureTrackPropertyTypes(cx, obj, range.front().propid());
|
||||
EnsureTrackPropertyTypes(cx, obj, range.front().propid());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1839,7 +1839,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
|||
|
||||
JitContext jctx(cx, temp);
|
||||
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!cx->compartment()->ensureJitCompartmentExists(cx))
|
||||
return AbortReason_Alloc;
|
||||
|
@ -1872,7 +1872,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
|||
return AbortReason_Alloc;
|
||||
}
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(*temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(*temp);
|
||||
if (!constraints)
|
||||
return AbortReason_Alloc;
|
||||
|
||||
|
@ -2645,8 +2645,8 @@ jit::InvalidateAll(FreeOp *fop, Zone *zone)
|
|||
|
||||
|
||||
void
|
||||
jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
const types::RecompileInfoVector &invalid, bool resetUses,
|
||||
jit::Invalidate(TypeZone &types, FreeOp *fop,
|
||||
const RecompileInfoVector &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
JitSpew(JitSpew_IonInvalidate, "Start invalidation.");
|
||||
|
@ -2655,7 +2655,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
|||
// to the traversal which frames have been invalidated.
|
||||
size_t numInvalidations = 0;
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
const types::CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
const CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
if (!co)
|
||||
continue;
|
||||
MOZ_ASSERT(co->isValid());
|
||||
|
@ -2688,7 +2688,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
|||
// IonScript will be immediately destroyed. Otherwise, it will be held live
|
||||
// until its last invalidated frame is destroyed.
|
||||
for (size_t i = 0; i < invalid.length(); i++) {
|
||||
types::CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
CompilerOutput *co = invalid[i].compilerOutput(types);
|
||||
if (!co)
|
||||
continue;
|
||||
MOZ_ASSERT(co->isValid());
|
||||
|
@ -2716,7 +2716,7 @@ jit::Invalidate(types::TypeZone &types, FreeOp *fop,
|
|||
}
|
||||
|
||||
void
|
||||
jit::Invalidate(JSContext *cx, const types::RecompileInfoVector &invalid, bool resetUses,
|
||||
jit::Invalidate(JSContext *cx, const RecompileInfoVector &invalid, bool resetUses,
|
||||
bool cancelOffThread)
|
||||
{
|
||||
jit::Invalidate(cx->zone()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses,
|
||||
|
@ -2727,7 +2727,7 @@ bool
|
|||
jit::IonScript::invalidate(JSContext *cx, bool resetUses, const char *reason)
|
||||
{
|
||||
JitSpew(JitSpew_IonInvalidate, " Invalidate IonScript %p: %s", this, reason);
|
||||
types::RecompileInfoVector list;
|
||||
RecompileInfoVector list;
|
||||
if (!list.append(recompileInfo()))
|
||||
return false;
|
||||
Invalidate(cx, list, resetUses, true);
|
||||
|
@ -2760,7 +2760,7 @@ jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffT
|
|||
js_free(buf);
|
||||
}
|
||||
|
||||
types::RecompileInfoVector scripts;
|
||||
RecompileInfoVector scripts;
|
||||
MOZ_ASSERT(script->hasIonScript());
|
||||
if (!scripts.append(script->ionScript()->recompileInfo()))
|
||||
return false;
|
||||
|
@ -2772,11 +2772,11 @@ jit::Invalidate(JSContext *cx, JSScript *script, bool resetUses, bool cancelOffT
|
|||
static void
|
||||
FinishInvalidationOf(FreeOp *fop, JSScript *script, IonScript *ionScript)
|
||||
{
|
||||
types::TypeZone &types = script->zone()->types;
|
||||
TypeZone &types = script->zone()->types;
|
||||
|
||||
// Note: If the script is about to be swept, the compiler output may have
|
||||
// already been destroyed.
|
||||
if (types::CompilerOutput *output = ionScript->recompileInfo().compilerOutput(types))
|
||||
if (CompilerOutput *output = ionScript->recompileInfo().compilerOutput(types))
|
||||
output->invalidate();
|
||||
|
||||
// If this script has Ion code on the stack, invalidated() will return
|
||||
|
|
|
@ -122,10 +122,10 @@ JitExecStatus IonCannon(JSContext *cx, RunState &state);
|
|||
JitExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args);
|
||||
|
||||
// Walk the stack and invalidate active Ion frames for the invalid scripts.
|
||||
void Invalidate(types::TypeZone &types, FreeOp *fop,
|
||||
const types::RecompileInfoVector &invalid, bool resetUses = true,
|
||||
void Invalidate(TypeZone &types, FreeOp *fop,
|
||||
const RecompileInfoVector &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
void Invalidate(JSContext *cx, const types::RecompileInfoVector &invalid, bool resetUses = true,
|
||||
void Invalidate(JSContext *cx, const RecompileInfoVector &invalid, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true,
|
||||
bool cancelOffThread = true);
|
||||
|
|
|
@ -2484,8 +2484,8 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
|||
{
|
||||
MOZ_ASSERT(!*eliminated);
|
||||
|
||||
const types::TemporaryTypeSet *barrierTypes = barrier->resultTypeSet();
|
||||
const types::TemporaryTypeSet *inputTypes = barrier->input()->resultTypeSet();
|
||||
const TemporaryTypeSet *barrierTypes = barrier->resultTypeSet();
|
||||
const TemporaryTypeSet *inputTypes = barrier->input()->resultTypeSet();
|
||||
|
||||
// Disregard the possible unbox added before the Typebarrier.
|
||||
if (barrier->input()->isUnbox() && barrier->input()->toUnbox()->mode() != MUnbox::Fallible)
|
||||
|
@ -2494,8 +2494,8 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
|||
if (!barrierTypes || !inputTypes)
|
||||
return true;
|
||||
|
||||
bool filtersNull = barrierTypes->filtersType(inputTypes, types::Type::NullType());
|
||||
bool filtersUndefined = barrierTypes->filtersType(inputTypes, types::Type::UndefinedType());
|
||||
bool filtersNull = barrierTypes->filtersType(inputTypes, TypeSet::NullType());
|
||||
bool filtersUndefined = barrierTypes->filtersType(inputTypes, TypeSet::UndefinedType());
|
||||
|
||||
if (!filtersNull && !filtersUndefined)
|
||||
return true;
|
||||
|
@ -2883,7 +2883,7 @@ static bool
|
|||
AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
||||
MDefinition *thisValue, MInstruction *ins, bool definitelyExecuted,
|
||||
HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList,
|
||||
Vector<TypeNewScript::Initializer> *initializerList,
|
||||
Vector<PropertyName *> *accessedProperties,
|
||||
bool *phandled)
|
||||
{
|
||||
|
@ -2926,7 +2926,7 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
|||
return true;
|
||||
|
||||
RootedId id(cx, NameToId(setprop->name()));
|
||||
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
// The prototype chain already contains a getter/setter for this
|
||||
// property, or type information is too imprecise.
|
||||
return true;
|
||||
|
@ -2952,14 +2952,14 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
|||
for (int i = callerResumePoints.length() - 1; i >= 0; i--) {
|
||||
MResumePoint *rp = callerResumePoints[i];
|
||||
JSScript *script = rp->block()->info().script();
|
||||
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP_FRAME,
|
||||
TypeNewScript::Initializer entry(TypeNewScript::Initializer::SETPROP_FRAME,
|
||||
script->pcToOffset(rp->pc()));
|
||||
if (!initializerList->append(entry))
|
||||
return false;
|
||||
}
|
||||
|
||||
JSScript *script = ins->block()->info().script();
|
||||
types::TypeNewScript::Initializer entry(types::TypeNewScript::Initializer::SETPROP,
|
||||
TypeNewScript::Initializer entry(TypeNewScript::Initializer::SETPROP,
|
||||
script->pcToOffset(setprop->resumePoint()->pc()));
|
||||
if (!initializerList->append(entry))
|
||||
return false;
|
||||
|
@ -2986,7 +2986,7 @@ AnalyzePoppedThis(JSContext *cx, ObjectGroup *group,
|
|||
if (!baseobj->lookup(cx, id) && !accessedProperties->append(get->name()))
|
||||
return false;
|
||||
|
||||
if (!types::AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, group, id)) {
|
||||
// The |this| value can escape if any property reads it does go
|
||||
// through a getter.
|
||||
return true;
|
||||
|
@ -3014,7 +3014,7 @@ CmpInstructions(const void *a, const void *b)
|
|||
bool
|
||||
jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
ObjectGroup *group, HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList)
|
||||
Vector<TypeNewScript::Initializer> *initializerList)
|
||||
{
|
||||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
|
||||
|
@ -3050,7 +3050,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
|||
return true;
|
||||
}
|
||||
|
||||
types::TypeScript::SetThis(cx, script, types::Type::ObjectType(group));
|
||||
TypeScript::SetThis(cx, script, TypeSet::ObjectType(group));
|
||||
|
||||
MIRGraph graph(&temp);
|
||||
InlineScriptTree *inlineScriptTree = InlineScriptTree::New(&temp, nullptr, nullptr, script);
|
||||
|
@ -3065,7 +3065,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
|||
|
||||
const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(temp);
|
||||
if (!constraints) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -3083,7 +3083,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
|||
return true;
|
||||
}
|
||||
|
||||
types::FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
|
@ -3183,7 +3183,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
|||
if (MResumePoint *rp = block->callerResumePoint()) {
|
||||
if (block->numPredecessors() == 1 && block->getPredecessor(0) == rp->block()) {
|
||||
JSScript *script = rp->block()->info().script();
|
||||
if (!types::AddClearDefiniteFunctionUsesInScript(cx, group, script, block->info().script()))
|
||||
if (!AddClearDefiniteFunctionUsesInScript(cx, group, script, block->info().script()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3234,7 +3234,7 @@ bool
|
|||
jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
||||
{
|
||||
RootedScript script(cx, scriptArg);
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
MOZ_ASSERT(!script->analyzedArgsUsage());
|
||||
|
||||
|
@ -3293,7 +3293,7 @@ jit::AnalyzeArgumentsUsage(JSContext *cx, JSScript *scriptArg)
|
|||
|
||||
const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
|
||||
|
||||
types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
|
||||
CompilerConstraintList *constraints = NewCompilerConstraintList(temp);
|
||||
if (!constraints)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ ConvertLinearInequality(TempAllocator &alloc, MBasicBlock *block, const LinearSu
|
|||
bool
|
||||
AnalyzeNewScriptDefiniteProperties(JSContext *cx, JSFunction *fun,
|
||||
ObjectGroup *group, HandlePlainObject baseobj,
|
||||
Vector<types::TypeNewScript::Initializer> *initializerList);
|
||||
Vector<TypeNewScript::Initializer> *initializerList);
|
||||
|
||||
bool
|
||||
AnalyzeArgumentsUsage(JSContext *cx, JSScript *script);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -218,7 +218,7 @@ class IonBuilder
|
|||
public:
|
||||
IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
|
||||
const JitCompileOptions &options, TempAllocator *temp,
|
||||
MIRGraph *graph, types::CompilerConstraintList *constraints,
|
||||
MIRGraph *graph, CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info,
|
||||
const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
|
||||
size_t inliningDepth = 0, uint32_t loopDepth = 0);
|
||||
|
@ -240,8 +240,8 @@ class IonBuilder
|
|||
|
||||
MInstruction *constantMaybeNursery(JSObject *obj);
|
||||
|
||||
JSFunction *getSingleCallTarget(types::TemporaryTypeSet *calleeTypes);
|
||||
bool getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constructing,
|
||||
JSFunction *getSingleCallTarget(TemporaryTypeSet *calleeTypes);
|
||||
bool getPolyCallTargets(TemporaryTypeSet *calleeTypes, bool constructing,
|
||||
ObjectVector &targets, uint32_t maxTargets);
|
||||
|
||||
void popCfgStack();
|
||||
|
@ -318,7 +318,7 @@ class IonBuilder
|
|||
// Incorporates a type/typeSet into an OSR value for a loop, after the loop
|
||||
// body has been processed.
|
||||
bool addOsrValueTypeBarrier(uint32_t slot, MInstruction **def,
|
||||
MIRType type, types::TemporaryTypeSet *typeSet);
|
||||
MIRType type, TemporaryTypeSet *typeSet);
|
||||
bool maybeAddOsrTypeBarriers();
|
||||
|
||||
// Restarts processing of a loop if the type information at its header was
|
||||
|
@ -358,18 +358,18 @@ class IonBuilder
|
|||
bool improveTypesAtCompare(MCompare *ins, bool trueBranch, MTest *test);
|
||||
// Used to detect triangular structure at test.
|
||||
bool detectAndOrStructure(MPhi *ins, bool *branchIsTrue);
|
||||
bool replaceTypeSet(MDefinition *subject, types::TemporaryTypeSet *type, MTest *test);
|
||||
bool replaceTypeSet(MDefinition *subject, TemporaryTypeSet *type, MTest *test);
|
||||
|
||||
// Add a guard which ensure that the set of type which goes through this
|
||||
// generated code correspond to the observed types for the bytecode.
|
||||
MDefinition *addTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed,
|
||||
MDefinition *addTypeBarrier(MDefinition *def, TemporaryTypeSet *observed,
|
||||
BarrierKind kind, MTypeBarrier **pbarrier = nullptr);
|
||||
bool pushTypeBarrier(MDefinition *def, types::TemporaryTypeSet *observed, BarrierKind kind);
|
||||
bool pushTypeBarrier(MDefinition *def, TemporaryTypeSet *observed, BarrierKind kind);
|
||||
|
||||
// As pushTypeBarrier, but will compute the needBarrier boolean itself based
|
||||
// on observed and the JSFunction that we're planning to call. The
|
||||
// JSFunction must be a DOM method or getter.
|
||||
bool pushDOMTypeBarrier(MInstruction *ins, types::TemporaryTypeSet *observed, JSFunction* func);
|
||||
bool pushDOMTypeBarrier(MInstruction *ins, TemporaryTypeSet *observed, JSFunction* func);
|
||||
|
||||
// If definiteType is not known or def already has the right type, just
|
||||
// returns def. Otherwise, returns an MInstruction that has that definite
|
||||
|
@ -378,7 +378,7 @@ class IonBuilder
|
|||
MDefinition *ensureDefiniteType(MDefinition* def, MIRType definiteType);
|
||||
|
||||
// Creates a MDefinition based on the given def improved with type as TypeSet.
|
||||
MDefinition *ensureDefiniteTypeSet(MDefinition* def, types::TemporaryTypeSet *types);
|
||||
MDefinition *ensureDefiniteTypeSet(MDefinition* def, TemporaryTypeSet *types);
|
||||
|
||||
JSObject *getSingletonPrototype(JSFunction *target);
|
||||
|
||||
|
@ -404,9 +404,9 @@ class IonBuilder
|
|||
|
||||
bool hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall);
|
||||
bool loadSlot(MDefinition *obj, size_t slot, size_t nfixed, MIRType rvalType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool storeSlot(MDefinition *obj, size_t slot, size_t nfixed,
|
||||
MDefinition *value, bool needsBarrier,
|
||||
MIRType slotType = MIRType_None);
|
||||
|
@ -418,19 +418,19 @@ class IonBuilder
|
|||
// jsop_getprop() helpers.
|
||||
bool checkIsDefinitelyOptimizedArguments(MDefinition *obj, bool *isOptimizedArgs);
|
||||
bool getPropTryInferredConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj);
|
||||
bool getPropTryArgumentsCallee(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryUnboxed(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
bool getPropTryTypedObject(bool *emitted, MDefinition *obj, PropertyName *name);
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
|
@ -444,25 +444,25 @@ class IonBuilder
|
|||
TypedObjectPrediction fieldTypeReprs,
|
||||
size_t fieldIndex);
|
||||
bool getPropTryInnerize(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
TemporaryTypeSet *types);
|
||||
bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
|
||||
// jsop_setprop() helpers.
|
||||
bool setPropTryCommonSetter(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value);
|
||||
bool setPropTryCommonDOMSetter(bool *emitted, MDefinition *obj,
|
||||
MDefinition *value, JSFunction *setter,
|
||||
types::TemporaryTypeSet *objTypes);
|
||||
TemporaryTypeSet *objTypes);
|
||||
bool setPropTryDefiniteSlot(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryUnboxed(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryInlineAccess(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
bool setPropTryTypedObject(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value);
|
||||
bool setPropTryReferencePropOfTypedObject(bool *emitted,
|
||||
|
@ -478,11 +478,11 @@ class IonBuilder
|
|||
TypedObjectPrediction fieldTypeReprs);
|
||||
bool setPropTryCache(bool *emitted, MDefinition *obj,
|
||||
PropertyName *name, MDefinition *value,
|
||||
bool barrier, types::TemporaryTypeSet *objTypes);
|
||||
bool barrier, TemporaryTypeSet *objTypes);
|
||||
|
||||
// binary data lookup helpers.
|
||||
TypedObjectPrediction typedObjectPrediction(MDefinition *typedObj);
|
||||
TypedObjectPrediction typedObjectPrediction(types::TemporaryTypeSet *types);
|
||||
TypedObjectPrediction typedObjectPrediction(TemporaryTypeSet *types);
|
||||
bool typedObjectHasField(MDefinition *typedObj,
|
||||
PropertyName *name,
|
||||
size_t *fieldOffset,
|
||||
|
@ -650,7 +650,7 @@ class IonBuilder
|
|||
bool jsop_getelem_dense(MDefinition *obj, MDefinition *index);
|
||||
bool jsop_getelem_typed(MDefinition *obj, MDefinition *index, ScalarTypeDescr::Type arrayType);
|
||||
bool jsop_setelem();
|
||||
bool jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion conversion,
|
||||
bool jsop_setelem_dense(TemporaryTypeSet::DoubleConversion conversion,
|
||||
SetElemSafety safety,
|
||||
MDefinition *object, MDefinition *index, MDefinition *value);
|
||||
bool jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
|
||||
|
@ -726,7 +726,7 @@ class IonBuilder
|
|||
// Native inlining helpers.
|
||||
// The typeset for the return value of our function. These are
|
||||
// the types it's been observed returning in the past.
|
||||
types::TemporaryTypeSet *getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *getInlineReturnTypeSet();
|
||||
// The known MIR type of getInlineReturnTypeSet.
|
||||
MIRType getInlineReturnType();
|
||||
|
||||
|
@ -863,18 +863,18 @@ class IonBuilder
|
|||
MBasicBlock *bottom);
|
||||
MDefinition *specializeInlinedReturn(MDefinition *rdef, MBasicBlock *exit);
|
||||
|
||||
bool objectsHaveCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
bool objectsHaveCommonPrototype(TemporaryTypeSet *types, PropertyName *name,
|
||||
bool isGetter, JSObject *foundProto, bool *guardGlobal);
|
||||
void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
void freezePropertiesForCommonPrototype(TemporaryTypeSet *types, PropertyName *name,
|
||||
JSObject *foundProto, bool allowEmptyTypesForGlobal = false);
|
||||
/*
|
||||
* Callers must pass a non-null globalGuard if they pass a non-null globalShape.
|
||||
*/
|
||||
bool testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
bool testCommonGetterSetter(TemporaryTypeSet *types, PropertyName *name,
|
||||
bool isGetter, JSObject *foundProto, Shape *lastProperty,
|
||||
MDefinition **guard, Shape *globalShape = nullptr,
|
||||
MDefinition **globalGuard = nullptr);
|
||||
bool testShouldDOMCall(types::TypeSet *inTypes,
|
||||
bool testShouldDOMCall(TypeSet *inTypes,
|
||||
JSFunction *func, JSJitInfo::OpType opType);
|
||||
|
||||
MDefinition *addShapeGuardsForGetterSetter(MDefinition *obj, JSObject *holder, Shape *holderShape,
|
||||
|
@ -882,27 +882,27 @@ class IonBuilder
|
|||
bool isOwnProperty);
|
||||
|
||||
bool annotateGetPropertyCache(MDefinition *obj, MGetPropertyCache *getPropCache,
|
||||
types::TemporaryTypeSet *objTypes,
|
||||
types::TemporaryTypeSet *pushedTypes);
|
||||
TemporaryTypeSet *objTypes,
|
||||
TemporaryTypeSet *pushedTypes);
|
||||
|
||||
MGetPropertyCache *getInlineableGetPropertyCache(CallInfo &callInfo);
|
||||
|
||||
JSObject *testSingletonProperty(JSObject *obj, PropertyName *name);
|
||||
bool testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, PropertyName *name,
|
||||
bool *testObject, bool *testString);
|
||||
uint32_t getDefiniteSlot(types::TemporaryTypeSet *types, PropertyName *name);
|
||||
uint32_t getUnboxedOffset(types::TemporaryTypeSet *types, PropertyName *name,
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet *types, PropertyName *name);
|
||||
uint32_t getUnboxedOffset(TemporaryTypeSet *types, PropertyName *name,
|
||||
JSValueType *punboxedType);
|
||||
MInstruction *loadUnboxedProperty(MDefinition *obj, size_t offset, JSValueType unboxedType,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
BarrierKind barrier, TemporaryTypeSet *types);
|
||||
MInstruction *storeUnboxedProperty(MDefinition *obj, size_t offset, JSValueType unboxedType,
|
||||
MDefinition *value);
|
||||
bool freezePropTypeSets(types::TemporaryTypeSet *types,
|
||||
bool freezePropTypeSets(TemporaryTypeSet *types,
|
||||
JSObject *foundProto, PropertyName *name);
|
||||
bool canInlinePropertyOpShapes(const BaselineInspector::ShapeVector &nativeShapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups);
|
||||
|
||||
types::TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
|
||||
TemporaryTypeSet *bytecodeTypes(jsbytecode *pc);
|
||||
|
||||
// Use one of the below methods for updating the current block, rather than
|
||||
// updating |current| directly. setCurrent() should only be used in cases
|
||||
|
@ -946,7 +946,7 @@ class IonBuilder
|
|||
CodeGenerator *backgroundCodegen() const { return backgroundCodegen_; }
|
||||
void setBackgroundCodegen(CodeGenerator *codegen) { backgroundCodegen_ = codegen; }
|
||||
|
||||
types::CompilerConstraintList *constraints() {
|
||||
CompilerConstraintList *constraints() {
|
||||
return constraints_;
|
||||
}
|
||||
|
||||
|
@ -978,7 +978,7 @@ class IonBuilder
|
|||
BaselineFrameInspector *baselineFrame_;
|
||||
|
||||
// Constraints for recording dependencies on type information.
|
||||
types::CompilerConstraintList *constraints_;
|
||||
CompilerConstraintList *constraints_;
|
||||
|
||||
// Basic analysis information about the script.
|
||||
BytecodeAnalysis analysis_;
|
||||
|
@ -986,7 +986,7 @@ class IonBuilder
|
|||
return analysis_;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
|
||||
TemporaryTypeSet *thisTypes, *argTypes, *typeArray;
|
||||
uint32_t typeArrayHint;
|
||||
uint32_t *bytecodeTypeMap;
|
||||
|
||||
|
@ -1119,7 +1119,7 @@ class IonBuilder
|
|||
// unchecked variants, despite the unchecked variants having no other
|
||||
// callers.
|
||||
void trackTypeInfo(JS::TrackedTypeSite site, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet)
|
||||
TemporaryTypeSet *typeSet)
|
||||
{
|
||||
if (MOZ_UNLIKELY(current->trackedSite()->hasOptimizations()))
|
||||
trackTypeInfoUnchecked(site, mirType, typeSet);
|
||||
|
@ -1156,7 +1156,7 @@ class IonBuilder
|
|||
// Out-of-line variants that don't check if optimization tracking is
|
||||
// enabled.
|
||||
void trackTypeInfoUnchecked(JS::TrackedTypeSite site, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet);
|
||||
TemporaryTypeSet *typeSet);
|
||||
void trackTypeInfoUnchecked(JS::TrackedTypeSite site, JSObject *obj);
|
||||
void trackTypeInfoUnchecked(CallInfo &callInfo);
|
||||
void trackOptimizationAttemptUnchecked(JS::TrackedStrategy strategy);
|
||||
|
@ -1292,7 +1292,7 @@ class CallInfo
|
|||
}
|
||||
};
|
||||
|
||||
bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
|
||||
bool TypeSetIncludes(TypeSet *types, MIRType input, TypeSet *inputTypes);
|
||||
|
||||
bool NeedsPostBarrier(CompileInfo &info, MDefinition *value);
|
||||
|
||||
|
|
|
@ -1268,10 +1268,9 @@ GetPropertyIC::allowArrayLength(Context cx, HandleObject obj) const
|
|||
CacheLocation *locs = ion->getCacheLocs(locationIndex);
|
||||
for (size_t i = 0; i < numLocations; i++) {
|
||||
CacheLocation &curLoc = locs[i];
|
||||
types::StackTypeSet *bcTypes =
|
||||
types::TypeScript::BytecodeTypes(curLoc.script, curLoc.pc);
|
||||
StackTypeSet *bcTypes = TypeScript::BytecodeTypes(curLoc.script, curLoc.pc);
|
||||
|
||||
if (!bcTypes->hasType(types::Type::Int32Type()))
|
||||
if (!bcTypes->hasType(TypeSet::Int32Type()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1855,7 +1854,7 @@ GetPropertyIC::update(JSContext *cx, size_t cacheIndex,
|
|||
|
||||
// Monitor changes to cache entry.
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, vp);
|
||||
TypeScript::Monitor(cx, script, pc, vp);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1900,11 +1899,11 @@ CheckTypeSetForWrite(MacroAssembler &masm, JSObject *obj, jsid id,
|
|||
ObjectGroup *group = obj->group();
|
||||
if (group->unknownProperties())
|
||||
return;
|
||||
types::HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
MOZ_ASSERT(propTypes);
|
||||
|
||||
// guardTypeSet can read from type sets without triggering read barriers.
|
||||
types::TypeSet::readBarrier(propTypes);
|
||||
TypeSet::readBarrier(propTypes);
|
||||
|
||||
Register scratch = object;
|
||||
masm.guardTypeSet(valReg, propTypes, BarrierKind::TypeSet, scratch, failure);
|
||||
|
@ -2581,7 +2580,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
|||
bool shouldCheck = false;
|
||||
ObjectGroup *group = obj->group();
|
||||
if (!group->unknownProperties()) {
|
||||
types::HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
HeapTypeSet *propTypes = group->maybeGetProperty(id);
|
||||
if (!propTypes)
|
||||
return false;
|
||||
if (!propTypes->unknown()) {
|
||||
|
@ -2590,7 +2589,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
|||
shouldCheck = true;
|
||||
if (val.constant()) {
|
||||
// If the input is a constant, then don't bother if the barrier will always fail.
|
||||
if (!propTypes->hasType(types::GetValueType(val.value())))
|
||||
if (!propTypes->hasType(TypeSet::GetValueType(val.value())))
|
||||
return false;
|
||||
shouldCheck = false;
|
||||
} else {
|
||||
|
@ -2601,7 +2600,7 @@ CanInlineSetPropTypeCheck(JSObject *obj, jsid id, ConstantOrRegister val, bool *
|
|||
// contains the specific object, but doesn't have ANYOBJECT set.
|
||||
if (reg.hasTyped() && reg.type() != MIRType_Object) {
|
||||
JSValueType valType = ValueTypeFromMIRType(reg.type());
|
||||
if (!propTypes->hasType(types::Type::PrimitiveType(valType)))
|
||||
if (!propTypes->hasType(TypeSet::PrimitiveType(valType)))
|
||||
return false;
|
||||
shouldCheck = false;
|
||||
}
|
||||
|
@ -3409,7 +3408,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
if (!GetObjectElementOperation(cx, JSOp(*pc), obj, idval, res))
|
||||
return false;
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3463,7 +3462,7 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
|||
}
|
||||
|
||||
if (!cache.monitoredResult())
|
||||
types::TypeScript::Monitor(cx, script, pc, res);
|
||||
TypeScript::Monitor(cx, script, pc, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4143,7 +4142,7 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
|||
}
|
||||
|
||||
// Monitor changes to cache entry.
|
||||
types::TypeScript::Monitor(cx, script, pc, vp);
|
||||
TypeScript::Monitor(cx, script, pc, vp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ struct IonScript
|
|||
uint32_t invalidationCount_;
|
||||
|
||||
// Identifier of the compilation which produced this code.
|
||||
types::RecompileInfo recompileInfo_;
|
||||
RecompileInfo recompileInfo_;
|
||||
|
||||
// The optimization level this script was compiled in.
|
||||
OptimizationLevel optimizationLevel_;
|
||||
|
@ -332,7 +332,7 @@ struct IonScript
|
|||
// Do not call directly, use IonScript::New. This is public for cx->new_.
|
||||
IonScript();
|
||||
|
||||
static IonScript *New(JSContext *cx, types::RecompileInfo recompileInfo,
|
||||
static IonScript *New(JSContext *cx, RecompileInfo recompileInfo,
|
||||
uint32_t frameSlots, uint32_t argumentSlots, uint32_t frameSize,
|
||||
size_t snapshotsListSize, size_t snapshotsRVATableSize,
|
||||
size_t recoversSize, size_t bailoutEntries,
|
||||
|
@ -541,10 +541,10 @@ struct IonScript
|
|||
if (!invalidationCount_)
|
||||
Destroy(fop, this);
|
||||
}
|
||||
const types::RecompileInfo& recompileInfo() const {
|
||||
const RecompileInfo& recompileInfo() const {
|
||||
return recompileInfo_;
|
||||
}
|
||||
types::RecompileInfo& recompileInfoRef() {
|
||||
RecompileInfo& recompileInfoRef() {
|
||||
return recompileInfo_;
|
||||
}
|
||||
OptimizationLevel optimizationLevel() const {
|
||||
|
|
|
@ -2115,7 +2115,7 @@ SnapshotIterator::computeInstructionResults(JSContext *cx, RInstructionResults *
|
|||
|
||||
// Use AutoEnterAnalysis to avoid invoking the object metadata callback,
|
||||
// which could try to walk the stack while bailing out.
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
// Fill with the results of recover instructions.
|
||||
SnapshotIterator s(*this);
|
||||
|
|
|
@ -2295,7 +2295,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
// Requesting a non-GC pointer is safe here since we never re-enter C++
|
||||
// from inside a type barrier test.
|
||||
|
||||
const types::TemporaryTypeSet *types = ins->resultTypeSet();
|
||||
const TemporaryTypeSet *types = ins->resultTypeSet();
|
||||
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
|
||||
|
||||
MIRType inputType = ins->getOperand(0)->type();
|
||||
|
@ -2325,7 +2325,7 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||
}
|
||||
|
||||
// Handle typebarrier with specific ObjectGroup/SingleObjects.
|
||||
if (inputType == MIRType_Object && !types->hasType(types::Type::AnyObjectType()) &&
|
||||
if (inputType == MIRType_Object && !types->hasType(TypeSet::AnyObjectType()) &&
|
||||
ins->barrierKind() != BarrierKind::TypeTagOnly)
|
||||
{
|
||||
LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
|
||||
|
@ -2346,7 +2346,7 @@ LIRGenerator::visitMonitorTypes(MMonitorTypes *ins)
|
|||
// Requesting a non-GC pointer is safe here since we never re-enter C++
|
||||
// from inside a type check.
|
||||
|
||||
const types::TemporaryTypeSet *types = ins->typeSet();
|
||||
const TemporaryTypeSet *types = ins->typeSet();
|
||||
bool needTemp = !types->unknownObject() && types->getObjectCount() > 0;
|
||||
LDefinition tmp = needTemp ? temp() : tempToUnbox();
|
||||
|
||||
|
|
|
@ -274,7 +274,7 @@ IonBuilder::inlineNativeGetter(CallInfo &callInfo, JSFunction *target)
|
|||
if (!optimizationInfo().inlineNative())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
MOZ_ASSERT(callInfo.argc() == 0);
|
||||
|
||||
// Try to optimize typed array lengths. There is one getter on
|
||||
|
@ -321,7 +321,7 @@ IonBuilder::inlineNonFunctionCall(CallInfo &callInfo, JSObject *target)
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
TemporaryTypeSet *
|
||||
IonBuilder::getInlineReturnTypeSet()
|
||||
{
|
||||
return bytecodeTypes(pc);
|
||||
|
@ -330,7 +330,7 @@ IonBuilder::getInlineReturnTypeSet()
|
|||
MIRType
|
||||
IonBuilder::getInlineReturnType()
|
||||
{
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
return returnTypes->getKnownMIRType();
|
||||
}
|
||||
|
||||
|
@ -377,9 +377,9 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
|||
initLength = callInfo.argc();
|
||||
allocating = NewArray_FullyAllocating;
|
||||
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(templateArray);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(templateArray);
|
||||
if (!key->unknownProperties()) {
|
||||
types::HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
|
||||
for (uint32_t i = 0; i < initLength; i++) {
|
||||
MDefinition *value = callInfo.getArg(i);
|
||||
|
@ -391,9 +391,9 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
|||
}
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
getInlineReturnTypeSet()->convertDoubleElements(constraints());
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles)
|
||||
templateArray->setShouldConvertDoubleElements();
|
||||
else
|
||||
templateArray->clearShouldConvertDoubleElements();
|
||||
|
@ -461,7 +461,7 @@ IonBuilder::inlineArray(CallInfo &callInfo)
|
|||
current->add(id);
|
||||
|
||||
MDefinition *value = callInfo.getArg(i);
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles) {
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles) {
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
current->add(valueDouble);
|
||||
value = valueDouble;
|
||||
|
@ -512,7 +512,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
|||
OBJECT_FLAG_ITERATED;
|
||||
|
||||
MDefinition *obj = callInfo.thisArg();
|
||||
types::TemporaryTypeSet *thisTypes = obj->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes || thisTypes->getKnownClass(constraints()) != &ArrayObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
if (thisTypes->hasObjectFlags(constraints(), unhandledFlags)) {
|
||||
|
@ -520,7 +520,7 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -529,9 +529,9 @@ IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
|||
|
||||
obj = addMaybeCopyElementsForWrite(obj);
|
||||
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_NON_PACKED);
|
||||
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
|
||||
bool maybeUndefined = returnTypes->hasType(TypeSet::UndefinedType());
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, nullptr, returnTypes);
|
||||
|
@ -640,7 +640,7 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
|||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
if (!thisTypes || thisTypes->getKnownClass(constraints()) != &ArrayObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
if (thisTypes->hasObjectFlags(constraints(), OBJECT_FLAG_SPARSE_INDEXES |
|
||||
|
@ -650,14 +650,14 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
thisTypes->convertDoubleElements(constraints());
|
||||
if (conversion == types::TemporaryTypeSet::AmbiguousDoubleConversion) {
|
||||
if (conversion == TemporaryTypeSet::AmbiguousDoubleConversion) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ArrayDoubleConversion);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -665,8 +665,8 @@ IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
|||
callInfo.setImplicitlyUsedUnchecked();
|
||||
value = callInfo.getArg(0);
|
||||
|
||||
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles ||
|
||||
conversion == types::TemporaryTypeSet::MaybeConvertToDoubles)
|
||||
if (conversion == TemporaryTypeSet::AlwaysConvertToDoubles ||
|
||||
conversion == TemporaryTypeSet::MaybeConvertToDoubles)
|
||||
{
|
||||
MInstruction *valueDouble = MToDouble::New(alloc(), value);
|
||||
current->add(valueDouble);
|
||||
|
@ -704,8 +704,8 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
|
||||
// |this| and the argument must be dense arrays.
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
types::TemporaryTypeSet *argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *argTypes = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!thisTypes || !argTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
|
@ -728,7 +728,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
|||
}
|
||||
|
||||
// Watch out for indexed properties on the prototype.
|
||||
if (types::ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
if (ArrayPrototypeHasIndexedProperty(constraints(), script())) {
|
||||
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -741,7 +741,7 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
|||
ObjectGroup *thisGroup = thisTypes->getGroup(0);
|
||||
if (!thisGroup)
|
||||
return InliningStatus_NotInlined;
|
||||
types::TypeSetObjectKey *thisKey = types::TypeSetObjectKey::get(thisGroup);
|
||||
TypeSet::ObjectKey *thisKey = TypeSet::ObjectKey::get(thisGroup);
|
||||
if (thisKey->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
|
@ -757,21 +757,21 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
|||
// Constraints modeling this concat have not been generated by inference,
|
||||
// so check that type information already reflects possible side effects of
|
||||
// this call.
|
||||
types::HeapTypeSetKey thisElemTypes = thisKey->property(JSID_VOID);
|
||||
HeapTypeSetKey thisElemTypes = thisKey->property(JSID_VOID);
|
||||
|
||||
types::TemporaryTypeSet *resTypes = getInlineReturnTypeSet();
|
||||
if (!resTypes->hasType(types::Type::ObjectType(thisKey)))
|
||||
TemporaryTypeSet *resTypes = getInlineReturnTypeSet();
|
||||
if (!resTypes->hasType(TypeSet::ObjectType(thisKey)))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
for (unsigned i = 0; i < argTypes->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = argTypes->getObject(i);
|
||||
TypeSet::ObjectKey *key = argTypes->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elemTypes = key->property(JSID_VOID);
|
||||
if (!elemTypes.knownSubset(constraints(), thisElemTypes))
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -1236,11 +1236,11 @@ IonBuilder::inlineMathFRound(CallInfo &callInfo)
|
|||
|
||||
// MIRType can't be Float32, as this point, as getInlineReturnType uses JSVal types
|
||||
// to infer the returned MIR type.
|
||||
types::TemporaryTypeSet *returned = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returned = getInlineReturnTypeSet();
|
||||
if (returned->empty()) {
|
||||
// As there's only one possible returned type, just add it to the observed
|
||||
// returned typeset
|
||||
returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc());
|
||||
returned->addType(TypeSet::DoubleType(), alloc_->lifoAlloc());
|
||||
} else {
|
||||
MIRType returnType = getInlineReturnType();
|
||||
if (!IsNumberType(returnType))
|
||||
|
@ -1377,15 +1377,15 @@ IonBuilder::inlineStringSplit(CallInfo &callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
MOZ_ASSERT(templateObject->is<ArrayObject>());
|
||||
|
||||
types::TypeSetObjectKey *retKey = types::TypeSetObjectKey::get(templateObject);
|
||||
TypeSet::ObjectKey *retKey = TypeSet::ObjectKey::get(templateObject);
|
||||
if (retKey->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::HeapTypeSetKey key = retKey->property(JSID_VOID);
|
||||
HeapTypeSetKey key = retKey->property(JSID_VOID);
|
||||
if (!key.maybeTypes())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (!key.maybeTypes()->hasType(types::Type::StringType())) {
|
||||
if (!key.maybeTypes()->hasType(TypeSet::StringType())) {
|
||||
key.freeze(constraints());
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
@ -1547,7 +1547,7 @@ IonBuilder::inlineRegExpExec(CallInfo &callInfo)
|
|||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
const Class *clasp = thisTypes ? thisTypes->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
|
@ -1588,7 +1588,7 @@ IonBuilder::inlineRegExpTest(CallInfo &callInfo)
|
|||
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
const Class *clasp = thisTypes ? thisTypes->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
|
@ -1627,7 +1627,7 @@ IonBuilder::inlineStrReplace(CallInfo &callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
|
||||
// Arg 0: RegExp.
|
||||
types::TemporaryTypeSet *arg0Type = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *arg0Type = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *clasp = arg0Type ? arg0Type->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp != &RegExpObject::class_ && callInfo.getArg(0)->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
|
@ -1704,7 +1704,7 @@ IonBuilder::inlineObjectCreate(CallInfo &callInfo)
|
|||
if (IsInsideNursery(proto))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *types = arg->resultTypeSet();
|
||||
TemporaryTypeSet *types = arg->resultTypeSet();
|
||||
if (!types || types->maybeSingleton() != proto)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
|
@ -1851,7 +1851,7 @@ IonBuilder::inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base)
|
|||
MDefinition *id = callInfo.getArg(base + 1);
|
||||
MDefinition *elem = callInfo.getArg(base + 2);
|
||||
|
||||
types::TemporaryTypeSet::DoubleConversion conversion =
|
||||
TemporaryTypeSet::DoubleConversion conversion =
|
||||
obj->resultTypeSet()->convertDoubleElements(constraints());
|
||||
if (!jsop_setelem_dense(conversion, SetElem_Unsafe, obj, id, elem))
|
||||
return false;
|
||||
|
@ -1913,7 +1913,7 @@ IonBuilder::inlineHasClass(CallInfo &callInfo,
|
|||
if (getInlineReturnType() != MIRType_Boolean)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *knownClass = types ? types->getKnownClass(constraints()) : nullptr;
|
||||
if (knownClass) {
|
||||
pushConstant(BooleanValue(knownClass == clasp1 ||
|
||||
|
@ -1966,20 +1966,20 @@ IonBuilder::inlineIsTypedArray(CallInfo &callInfo)
|
|||
// The test is elaborate: in-line only if there is exact
|
||||
// information.
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!types)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
bool result = false;
|
||||
switch (types->forAllClasses(constraints(), IsTypedArrayClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
result = false;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
result = true;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
|
@ -2026,20 +2026,20 @@ IonBuilder::inlineObjectIsTypeDescr(CallInfo &callInfo)
|
|||
// The test is elaborate: in-line only if there is exact
|
||||
// information.
|
||||
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!types)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
bool result = false;
|
||||
switch (types->forAllClasses(constraints(), IsTypeDescrClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
result = false;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
result = true;
|
||||
break;
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
|
@ -2070,15 +2070,15 @@ IonBuilder::inlineSetTypedObjectOffset(CallInfo &callInfo)
|
|||
// with TI or because of something else -- but we'll just let it
|
||||
// fall through to the SetTypedObjectOffset intrinsic in such
|
||||
// cases.
|
||||
types::TemporaryTypeSet *types = typedObj->resultTypeSet();
|
||||
TemporaryTypeSet *types = typedObj->resultTypeSet();
|
||||
if (typedObj->type() != MIRType_Object || !types)
|
||||
return InliningStatus_NotInlined;
|
||||
switch (types->forAllClasses(constraints(), IsTypedObjectClass)) {
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case types::TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case types::TemporaryTypeSet::ForAllResult::MIXED:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
|
||||
case TemporaryTypeSet::ForAllResult::EMPTY:
|
||||
case TemporaryTypeSet::ForAllResult::MIXED:
|
||||
return InliningStatus_NotInlined;
|
||||
case types::TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2188,7 +2188,7 @@ IonBuilder::inlineIsCallable(CallInfo &callInfo)
|
|||
isCallableKnown = true;
|
||||
isCallableConstant = false;
|
||||
} else {
|
||||
types::TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *types = callInfo.getArg(0)->resultTypeSet();
|
||||
const Class *clasp = types ? types->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp && !clasp->isProxy()) {
|
||||
isCallableKnown = true;
|
||||
|
@ -2588,7 +2588,7 @@ IonBuilder::atomicsMeetsPreconditions(CallInfo &callInfo, Scalar::Type *arrayTyp
|
|||
// optimize and that the return type is suitable for that element
|
||||
// type.
|
||||
|
||||
types::TemporaryTypeSet *arg0Types = callInfo.getArg(0)->resultTypeSet();
|
||||
TemporaryTypeSet *arg0Types = callInfo.getArg(0)->resultTypeSet();
|
||||
if (!arg0Types)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ MDefinition::mightBeMagicType() const
|
|||
if (MIRType_Value != type())
|
||||
return false;
|
||||
|
||||
return !resultTypeSet() || resultTypeSet()->hasType(types::Type::MagicArgType());
|
||||
return !resultTypeSet() || resultTypeSet()->hasType(TypeSet::MagicArgType());
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
|
@ -339,12 +339,12 @@ MInstruction::clearResumePoint()
|
|||
}
|
||||
|
||||
static bool
|
||||
MaybeEmulatesUndefined(types::CompilerConstraintList *constraints, MDefinition *op)
|
||||
MaybeEmulatesUndefined(CompilerConstraintList *constraints, MDefinition *op)
|
||||
{
|
||||
if (!op->mightBeType(MIRType_Object))
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = op->resultTypeSet();
|
||||
TemporaryTypeSet *types = op->resultTypeSet();
|
||||
if (!types)
|
||||
return true;
|
||||
|
||||
|
@ -352,12 +352,12 @@ MaybeEmulatesUndefined(types::CompilerConstraintList *constraints, MDefinition *
|
|||
}
|
||||
|
||||
static bool
|
||||
MaybeCallable(types::CompilerConstraintList *constraints, MDefinition *op)
|
||||
MaybeCallable(CompilerConstraintList *constraints, MDefinition *op)
|
||||
{
|
||||
if (!op->mightBeType(MIRType_Object))
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = op->resultTypeSet();
|
||||
TemporaryTypeSet *types = op->resultTypeSet();
|
||||
if (!types)
|
||||
return true;
|
||||
|
||||
|
@ -371,7 +371,7 @@ MTest::New(TempAllocator &alloc, MDefinition *ins, MBasicBlock *ifTrue, MBasicBl
|
|||
}
|
||||
|
||||
void
|
||||
MTest::cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints)
|
||||
MTest::cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
|
@ -621,13 +621,13 @@ MDefinition::emptyResultTypeSet() const
|
|||
}
|
||||
|
||||
MConstant *
|
||||
MConstant::New(TempAllocator &alloc, const Value &v, types::CompilerConstraintList *constraints)
|
||||
MConstant::New(TempAllocator &alloc, const Value &v, CompilerConstraintList *constraints)
|
||||
{
|
||||
return new(alloc) MConstant(v, constraints);
|
||||
}
|
||||
|
||||
MConstant *
|
||||
MConstant::NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type, types::CompilerConstraintList *constraints)
|
||||
MConstant::NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type, CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(!IsSimdType(type));
|
||||
MConstant *constant = new(alloc) MConstant(v, constraints);
|
||||
|
@ -647,29 +647,29 @@ MConstant::NewConstraintlessObject(TempAllocator &alloc, JSObject *v)
|
|||
return new(alloc) MConstant(v);
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
jit::MakeSingletonTypeSet(types::CompilerConstraintList *constraints, JSObject *obj)
|
||||
TemporaryTypeSet *
|
||||
jit::MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj)
|
||||
{
|
||||
// Invalidate when this object's ObjectGroup gets unknown properties. This
|
||||
// happens for instance when we mutate an object's __proto__, in this case
|
||||
// we want to invalidate and mark this TypeSet as containing AnyObject
|
||||
// (because mutating __proto__ will change an object's ObjectGroup).
|
||||
MOZ_ASSERT(constraints);
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
key->hasStableClassAndProto(constraints);
|
||||
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::ObjectType(obj));
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::ObjectType(obj));
|
||||
}
|
||||
|
||||
static types::TemporaryTypeSet *
|
||||
static TemporaryTypeSet *
|
||||
MakeUnknownTypeSet()
|
||||
{
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, types::Type::UnknownType());
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, TypeSet::UnknownType());
|
||||
}
|
||||
|
||||
MConstant::MConstant(const js::Value &vp, types::CompilerConstraintList *constraints)
|
||||
MConstant::MConstant(const js::Value &vp, CompilerConstraintList *constraints)
|
||||
: value_(vp)
|
||||
{
|
||||
setResultType(MIRTypeFromValue(vp));
|
||||
|
@ -806,7 +806,7 @@ MConstant::canProduceFloat32() const
|
|||
return true;
|
||||
}
|
||||
|
||||
MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints)
|
||||
MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, CompilerConstraintList *constraints)
|
||||
: index_(index)
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
|
@ -820,7 +820,7 @@ MNurseryObject::MNurseryObject(JSObject *obj, uint32_t index, types::CompilerCon
|
|||
|
||||
MNurseryObject *
|
||||
MNurseryObject::New(TempAllocator &alloc, JSObject *obj, uint32_t index,
|
||||
types::CompilerConstraintList *constraints)
|
||||
CompilerConstraintList *constraints)
|
||||
{
|
||||
return new(alloc) MNurseryObject(obj, index, constraints);
|
||||
}
|
||||
|
@ -1107,7 +1107,7 @@ MMathFunction::foldsTo(TempAllocator &alloc)
|
|||
}
|
||||
|
||||
MParameter *
|
||||
MParameter::New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types)
|
||||
MParameter::New(TempAllocator &alloc, int32_t index, TemporaryTypeSet *types)
|
||||
{
|
||||
return new(alloc) MParameter(index, types);
|
||||
}
|
||||
|
@ -1624,20 +1624,20 @@ MPhi::congruentTo(const MDefinition *ins) const
|
|||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
||||
static inline types::TemporaryTypeSet *
|
||||
static inline TemporaryTypeSet *
|
||||
MakeMIRTypeSet(MIRType type)
|
||||
{
|
||||
MOZ_ASSERT(type != MIRType_Value);
|
||||
types::Type ntype = type == MIRType_Object
|
||||
? types::Type::AnyObjectType()
|
||||
: types::Type::PrimitiveType(ValueTypeFromMIRType(type));
|
||||
TypeSet::Type ntype = type == MIRType_Object
|
||||
? TypeSet::AnyObjectType()
|
||||
: TypeSet::PrimitiveType(ValueTypeFromMIRType(type));
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
return alloc->new_<types::TemporaryTypeSet>(alloc, ntype);
|
||||
return alloc->new_<TemporaryTypeSet>(alloc, ntype);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, types::TemporaryTypeSet *newTypeSet)
|
||||
jit::MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet *newTypeSet)
|
||||
{
|
||||
if (newTypeSet && newTypeSet->empty())
|
||||
return true;
|
||||
|
@ -1664,7 +1664,7 @@ jit::MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
|||
}
|
||||
if (newTypeSet) {
|
||||
if (!newTypeSet->isSubset(*ptypeSet))
|
||||
*ptypeSet = types::TypeSet::unionSets(*ptypeSet, newTypeSet, alloc);
|
||||
*ptypeSet = TypeSet::unionSets(*ptypeSet, newTypeSet, alloc);
|
||||
} else {
|
||||
*ptypeSet = nullptr;
|
||||
}
|
||||
|
@ -1694,7 +1694,7 @@ MPhi::specializeType()
|
|||
}
|
||||
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
for (size_t i = start; i < inputs_.length(); i++) {
|
||||
MDefinition *def = getOperand(i);
|
||||
|
@ -1708,13 +1708,13 @@ MPhi::specializeType()
|
|||
}
|
||||
|
||||
bool
|
||||
MPhi::addBackedgeType(MIRType type, types::TemporaryTypeSet *typeSet)
|
||||
MPhi::addBackedgeType(MIRType type, TemporaryTypeSet *typeSet)
|
||||
{
|
||||
MOZ_ASSERT(!specialized_);
|
||||
|
||||
if (hasBackedgeType_) {
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, type, typeSet))
|
||||
return false;
|
||||
|
@ -1735,7 +1735,7 @@ MPhi::typeIncludes(MDefinition *def)
|
|||
if (def->type() == MIRType_Int32 && this->type() == MIRType_Double)
|
||||
return true;
|
||||
|
||||
if (types::TemporaryTypeSet *types = def->resultTypeSet()) {
|
||||
if (TemporaryTypeSet *types = def->resultTypeSet()) {
|
||||
if (this->resultTypeSet())
|
||||
return types->isSubset(this->resultTypeSet());
|
||||
if (this->type() == MIRType_Value || types->empty())
|
||||
|
@ -1756,7 +1756,7 @@ bool
|
|||
MPhi::checkForTypeChange(MDefinition *ins, bool *ptypeChange)
|
||||
{
|
||||
MIRType resultType = this->type();
|
||||
types::TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
TemporaryTypeSet *resultTypeSet = this->resultTypeSet();
|
||||
|
||||
if (!MergeTypes(&resultType, &resultTypeSet, ins->type(), ins->resultTypeSet()))
|
||||
return false;
|
||||
|
@ -2468,7 +2468,7 @@ MBinaryArithInstruction::inferFallback(BaselineInspector *inspector,
|
|||
// either to avoid degrading subsequent analysis.
|
||||
if (getOperand(0)->emptyResultTypeSet() || getOperand(1)->emptyResultTypeSet()) {
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
types::TemporaryTypeSet *types = alloc->new_<types::TemporaryTypeSet>();
|
||||
TemporaryTypeSet *types = alloc->new_<TemporaryTypeSet>();
|
||||
if (types)
|
||||
setResultTypeSet(types);
|
||||
}
|
||||
|
@ -2496,7 +2496,7 @@ ObjectOrSimplePrimitive(MDefinition *op)
|
|||
}
|
||||
|
||||
static bool
|
||||
CanDoValueBitwiseCmp(types::CompilerConstraintList *constraints,
|
||||
CanDoValueBitwiseCmp(CompilerConstraintList *constraints,
|
||||
MDefinition *lhs, MDefinition *rhs, bool looseEq)
|
||||
{
|
||||
// Only primitive (not double/string) or objects are supported.
|
||||
|
@ -2619,7 +2619,7 @@ MBinaryInstruction::tryUseUnsignedOperands()
|
|||
}
|
||||
|
||||
void
|
||||
MCompare::infer(types::CompilerConstraintList *constraints, BaselineInspector *inspector, jsbytecode *pc)
|
||||
MCompare::infer(CompilerConstraintList *constraints, BaselineInspector *inspector, jsbytecode *pc)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
|
@ -2827,7 +2827,7 @@ MTypeOf::foldsTo(TempAllocator &alloc)
|
|||
}
|
||||
|
||||
void
|
||||
MTypeOf::cacheInputMaybeCallableOrEmulatesUndefined(types::CompilerConstraintList *constraints)
|
||||
MTypeOf::cacheInputMaybeCallableOrEmulatesUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(inputMaybeCallableOrEmulatesUndefined());
|
||||
|
||||
|
@ -3568,7 +3568,7 @@ MCompare::filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *f
|
|||
}
|
||||
|
||||
void
|
||||
MNot::cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints)
|
||||
MNot::cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints)
|
||||
{
|
||||
MOZ_ASSERT(operandMightEmulateUndefined());
|
||||
|
||||
|
@ -4030,16 +4030,16 @@ InlinePropertyTable::hasFunction(JSFunction *func) const
|
|||
return false;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *
|
||||
TemporaryTypeSet *
|
||||
InlinePropertyTable::buildTypeSetForFunction(JSFunction *func) const
|
||||
{
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
types::TemporaryTypeSet *types = alloc->new_<types::TemporaryTypeSet>();
|
||||
TemporaryTypeSet *types = alloc->new_<TemporaryTypeSet>();
|
||||
if (!types)
|
||||
return nullptr;
|
||||
for (size_t i = 0; i < numEntries(); i++) {
|
||||
if (entries_[i]->func == func)
|
||||
types->addType(types::Type::ObjectType(entries_[i]->group), alloc);
|
||||
types->addType(TypeSet::ObjectType(entries_[i]->group), alloc);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
@ -4085,7 +4085,7 @@ MGetElementCache::allowDoubleResult() const
|
|||
if (!resultTypeSet())
|
||||
return true;
|
||||
|
||||
return resultTypeSet()->hasType(types::Type::DoubleType());
|
||||
return resultTypeSet()->hasType(TypeSet::DoubleType());
|
||||
}
|
||||
|
||||
size_t
|
||||
|
@ -4277,7 +4277,7 @@ MArrayJoin::foldsTo(TempAllocator &alloc) {
|
|||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessIsDenseNative(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id)
|
||||
{
|
||||
if (obj->mightBeType(MIRType_String))
|
||||
|
@ -4286,7 +4286,7 @@ jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
|||
if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
|
@ -4296,7 +4296,7 @@ jit::ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
|||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessIsAnyTypedArray(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id,
|
||||
Scalar::Type *arrayType)
|
||||
{
|
||||
|
@ -4306,7 +4306,7 @@ jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
|||
if (id->type() != MIRType_Int32 && id->type() != MIRType_Double)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
|
@ -4318,47 +4318,47 @@ jit::ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
|||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::ElementAccessIsPacked(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
return types && !types->hasObjectFlags(constraints, OBJECT_FLAG_NON_PACKED);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::ElementAccessMightBeCopyOnWrite(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
return !types || types->hasObjectFlags(constraints, OBJECT_FLAG_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
|
||||
jit::ElementAccessHasExtraIndexedProperty(CompilerConstraintList *constraints,
|
||||
MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
|
||||
if (!types || types->hasObjectFlags(constraints, OBJECT_FLAG_LENGTH_OVERFLOW))
|
||||
return true;
|
||||
|
||||
return types::TypeCanHaveExtraIndexedProperties(constraints, types);
|
||||
return TypeCanHaveExtraIndexedProperties(constraints, types);
|
||||
}
|
||||
|
||||
MIRType
|
||||
jit::DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj)
|
||||
jit::DenseNativeElementType(CompilerConstraintList *constraints, MDefinition *obj)
|
||||
{
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
MIRType elementType = MIRType_None;
|
||||
unsigned count = types->getObjectCount();
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties())
|
||||
return MIRType_None;
|
||||
|
||||
types::HeapTypeSetKey elementTypes = key->property(JSID_VOID);
|
||||
HeapTypeSetKey elementTypes = key->property(JSID_VOID);
|
||||
|
||||
MIRType type = elementTypes.knownMIRType(constraints);
|
||||
if (type == MIRType_None)
|
||||
|
@ -4374,9 +4374,9 @@ jit::DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinit
|
|||
}
|
||||
|
||||
static BarrierKind
|
||||
PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TypeSet *observed)
|
||||
PropertyReadNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TypeSet *observed)
|
||||
{
|
||||
// If the object being read from has types for the property which haven't
|
||||
// been observed at this access site, the read could produce a new type and
|
||||
|
@ -4393,7 +4393,7 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
|||
}
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (property.maybeTypes()) {
|
||||
if (!TypeSetIncludes(observed, MIRType_Value, property.maybeTypes())) {
|
||||
// If all possible objects have been observed, we don't have to
|
||||
|
@ -4412,7 +4412,7 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
|||
// other than undefined, a barrier is required.
|
||||
if (key->isSingleton()) {
|
||||
JSObject *obj = key->singleton();
|
||||
if (name && types::CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
|
||||
if (name && CanHaveEmptyPropertyTypesForOwnProperty(obj) &&
|
||||
(!property.maybeTypes() || property.maybeTypes()->empty()))
|
||||
{
|
||||
return BarrierKind::TypeSet;
|
||||
|
@ -4425,9 +4425,9 @@ PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
|||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved)
|
||||
CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TemporaryTypeSet *observed, bool updateObserved)
|
||||
{
|
||||
// If this access has never executed, try to add types to the observed set
|
||||
// according to any property which exists on the object or its prototype.
|
||||
|
@ -4442,14 +4442,14 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
|||
if (!obj->getClass()->isNative())
|
||||
break;
|
||||
|
||||
types::TypeSetObjectKey *key = types::TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
if (propertycx)
|
||||
key->ensureTrackedProperty(propertycx, NameToId(name));
|
||||
|
||||
if (!key->unknownProperties()) {
|
||||
types::HeapTypeSetKey property = key->property(NameToId(name));
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (property.maybeTypes()) {
|
||||
types::TypeSet::TypeList types;
|
||||
TypeSet::TypeList types;
|
||||
if (!property.maybeTypes()->enumerateTypes(&types))
|
||||
break;
|
||||
if (types.length()) {
|
||||
|
@ -4469,14 +4469,14 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
|||
|
||||
BarrierKind
|
||||
jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
if (observed->unknown())
|
||||
return BarrierKind::NoBarrier;
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return BarrierKind::TypeSet;
|
||||
|
||||
|
@ -4484,8 +4484,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
|||
|
||||
bool updateObserved = types->getObjectCount() == 1;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key) {
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i)) {
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, key, name,
|
||||
observed, updateObserved);
|
||||
if (kind == BarrierKind::TypeSet)
|
||||
|
@ -4504,21 +4503,21 @@ jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
|||
}
|
||||
|
||||
BarrierKind
|
||||
jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadOnPrototypeNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
if (observed->unknown())
|
||||
return BarrierKind::NoBarrier;
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return BarrierKind::TypeSet;
|
||||
|
||||
BarrierKind res = BarrierKind::NoBarrier;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
while (true) {
|
||||
|
@ -4526,7 +4525,7 @@ jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons
|
|||
return BarrierKind::TypeSet;
|
||||
if (!key->proto().isObject())
|
||||
break;
|
||||
key = types::TypeSetObjectKey::get(key->proto().toObject());
|
||||
key = TypeSet::ObjectKey::get(key->proto().toObject());
|
||||
BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, key, name, observed);
|
||||
if (kind == BarrierKind::TypeSet)
|
||||
return BarrierKind::TypeSet;
|
||||
|
@ -4544,23 +4543,22 @@ jit::PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons
|
|||
}
|
||||
|
||||
bool
|
||||
jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
jit::PropertyReadIsIdempotent(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name)
|
||||
{
|
||||
// Determine if reading a property from obj is likely to be idempotent.
|
||||
|
||||
types::TypeSet *types = obj->resultTypeSet();
|
||||
TypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key) {
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i)) {
|
||||
if (key->unknownProperties())
|
||||
return false;
|
||||
|
||||
// Check if the property has been reconfigured or is a getter.
|
||||
types::HeapTypeSetKey property = key->property(NameToId(name));
|
||||
HeapTypeSetKey property = key->property(NameToId(name));
|
||||
if (property.nonData(constraints))
|
||||
return false;
|
||||
}
|
||||
|
@ -4571,62 +4569,61 @@ jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
|||
|
||||
void
|
||||
jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
TemporaryTypeSet *observed)
|
||||
{
|
||||
// Add objects to observed which *could* be observed by reading name from obj,
|
||||
// to hopefully avoid unnecessary type barriers and code invalidations.
|
||||
|
||||
LifoAlloc *alloc = GetJitContext()->temp->lifoAlloc();
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
if (key->unknownProperties()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
types::HeapTypeSet *types = property.maybeTypes();
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSet *types = property.maybeTypes();
|
||||
if (!types)
|
||||
continue;
|
||||
|
||||
if (types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
observed->addType(TypeSet::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
if (key)
|
||||
observed->addType(types::Type::ObjectType(key), alloc);
|
||||
if (TypeSet::ObjectKey *key = types->getObject(i))
|
||||
observed->addType(TypeSet::ObjectType(key), alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
PropertyTypeIncludes(TempAllocator &alloc, types::HeapTypeSetKey property,
|
||||
PropertyTypeIncludes(TempAllocator &alloc, HeapTypeSetKey property,
|
||||
MDefinition *value, MIRType implicitType)
|
||||
{
|
||||
// If implicitType is not MIRType_None, it is an additional type which the
|
||||
// property implicitly includes. In this case, make a new type set which
|
||||
// explicitly contains the type.
|
||||
types::TypeSet *types = property.maybeTypes();
|
||||
TypeSet *types = property.maybeTypes();
|
||||
if (implicitType != MIRType_None) {
|
||||
types::Type newType = types::Type::PrimitiveType(ValueTypeFromMIRType(implicitType));
|
||||
TypeSet::Type newType = TypeSet::PrimitiveType(ValueTypeFromMIRType(implicitType));
|
||||
if (types)
|
||||
types = types->clone(alloc.lifoAlloc());
|
||||
else
|
||||
types = alloc.lifoAlloc()->new_<types::TemporaryTypeSet>();
|
||||
types = alloc.lifoAlloc()->new_<TemporaryTypeSet>();
|
||||
types->addType(newType, alloc.lifoAlloc());
|
||||
}
|
||||
|
||||
|
@ -4634,8 +4631,8 @@ PropertyTypeIncludes(TempAllocator &alloc, types::HeapTypeSetKey property,
|
|||
}
|
||||
|
||||
static bool
|
||||
TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, types::TemporaryTypeSet *objTypes,
|
||||
TryAddTypeBarrierForWrite(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, TemporaryTypeSet *objTypes,
|
||||
PropertyName *name, MDefinition **pvalue, MIRType implicitType)
|
||||
{
|
||||
// Return whether pvalue was modified to include a type barrier ensuring
|
||||
|
@ -4645,10 +4642,10 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
|||
// All objects in the set must have the same types for name. Otherwise, we
|
||||
// could bail out without subsequently triggering a type change that
|
||||
// invalidates the compiled code.
|
||||
Maybe<types::HeapTypeSetKey> aggregateProperty;
|
||||
Maybe<HeapTypeSetKey> aggregateProperty;
|
||||
|
||||
for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = objTypes->getObject(i);
|
||||
TypeSet::ObjectKey *key = objTypes->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
|
@ -4656,7 +4653,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
|||
return false;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (!property.maybeTypes() || property.couldBeConstant(constraints))
|
||||
return false;
|
||||
|
||||
|
@ -4704,7 +4701,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
|||
if ((*pvalue)->type() != MIRType_Value)
|
||||
return false;
|
||||
|
||||
types::TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
|
||||
TemporaryTypeSet *types = aggregateProperty->maybeTypes()->clone(alloc.lifoAlloc());
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
|
@ -4721,7 +4718,7 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
|||
|
||||
static MInstruction *
|
||||
AddGroupGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
|
||||
types::TypeSetObjectKey *key, bool bailOnEquality)
|
||||
TypeSet::ObjectKey *key, bool bailOnEquality)
|
||||
{
|
||||
MInstruction *guard;
|
||||
|
||||
|
@ -4742,8 +4739,8 @@ AddGroupGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
|
|||
|
||||
// Whether value can be written to property without changing type information.
|
||||
bool
|
||||
jit::CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
types::HeapTypeSetKey property, MDefinition *value,
|
||||
jit::CanWriteProperty(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
HeapTypeSetKey property, MDefinition *value,
|
||||
MIRType implicitType /* = MIRType_None */)
|
||||
{
|
||||
if (property.couldBeConstant(constraints))
|
||||
|
@ -4752,7 +4749,7 @@ jit::CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *const
|
|||
}
|
||||
|
||||
bool
|
||||
jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, MDefinition **pobj,
|
||||
PropertyName *name, MDefinition **pvalue,
|
||||
bool canModify, MIRType implicitType)
|
||||
|
@ -4763,7 +4760,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
|||
// properties that are accounted for by type information, i.e. normal data
|
||||
// properties and elements.
|
||||
|
||||
types::TemporaryTypeSet *types = (*pobj)->resultTypeSet();
|
||||
TemporaryTypeSet *types = (*pobj)->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return true;
|
||||
|
||||
|
@ -4774,7 +4771,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
|||
|
||||
bool success = true;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key || key->unknownProperties())
|
||||
continue;
|
||||
|
||||
|
@ -4784,7 +4781,7 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
|||
continue;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (!CanWriteProperty(alloc, constraints, property, *pvalue, implicitType)) {
|
||||
// Either pobj or pvalue needs to be modified to filter out the
|
||||
// types which the value could have but are not in the property,
|
||||
|
@ -4808,16 +4805,16 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstrai
|
|||
if (types->getObjectCount() <= 1)
|
||||
return true;
|
||||
|
||||
types::TypeSetObjectKey *excluded = nullptr;
|
||||
TypeSet::ObjectKey *excluded = nullptr;
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeSetObjectKey *key = types->getObject(i);
|
||||
TypeSet::ObjectKey *key = types->getObject(i);
|
||||
if (!key || key->unknownProperties())
|
||||
continue;
|
||||
if (!name && IsAnyTypedArrayClass(key->clasp()))
|
||||
continue;
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = key->property(id);
|
||||
HeapTypeSetKey property = key->property(id);
|
||||
if (CanWriteProperty(alloc, constraints, property, *pvalue, implicitType))
|
||||
continue;
|
||||
|
||||
|
|
152
js/src/jit/MIR.h
152
js/src/jit/MIR.h
|
@ -363,7 +363,7 @@ class MDefinition : public MNode
|
|||
uint32_t flags_; // Bit flags.
|
||||
Range *range_; // Any computed range for this def.
|
||||
MIRType resultType_; // Representation of result type.
|
||||
types::TemporaryTypeSet *resultTypeSet_; // Optional refinement of the result type.
|
||||
TemporaryTypeSet *resultTypeSet_; // Optional refinement of the result type.
|
||||
union {
|
||||
MInstruction *dependency_; // Implicit dependency (store, call, etc.) of this instruction.
|
||||
// Used by alias analysis, GVN and LICM.
|
||||
|
@ -608,7 +608,7 @@ class MDefinition : public MNode
|
|||
return resultType_;
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *resultTypeSet() const {
|
||||
TemporaryTypeSet *resultTypeSet() const {
|
||||
return resultTypeSet_;
|
||||
}
|
||||
bool emptyResultTypeSet() const;
|
||||
|
@ -781,7 +781,7 @@ class MDefinition : public MNode
|
|||
void setResultType(MIRType type) {
|
||||
resultType_ = type;
|
||||
}
|
||||
void setResultTypeSet(types::TemporaryTypeSet *types) {
|
||||
void setResultTypeSet(TemporaryTypeSet *types) {
|
||||
resultTypeSet_ = types;
|
||||
}
|
||||
|
||||
|
@ -1277,15 +1277,15 @@ class MConstant : public MNullaryInstruction
|
|||
Value value_;
|
||||
|
||||
protected:
|
||||
MConstant(const Value &v, types::CompilerConstraintList *constraints);
|
||||
MConstant(const Value &v, CompilerConstraintList *constraints);
|
||||
explicit MConstant(JSObject *obj);
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Constant)
|
||||
static MConstant *New(TempAllocator &alloc, const Value &v,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
static MConstant *NewTypedValue(TempAllocator &alloc, const Value &v, MIRType type,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
static MConstant *NewAsmJS(TempAllocator &alloc, const Value &v, MIRType type);
|
||||
static MConstant *NewConstraintlessObject(TempAllocator &alloc, JSObject *v);
|
||||
|
||||
|
@ -1335,12 +1335,12 @@ class MNurseryObject : public MNullaryInstruction
|
|||
uint32_t index_;
|
||||
|
||||
protected:
|
||||
MNurseryObject(JSObject *obj, uint32_t index, types::CompilerConstraintList *constraints);
|
||||
MNurseryObject(JSObject *obj, uint32_t index, CompilerConstraintList *constraints);
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NurseryObject)
|
||||
static MNurseryObject *New(TempAllocator &alloc, JSObject *obj, uint32_t index,
|
||||
types::CompilerConstraintList *constraints = nullptr);
|
||||
CompilerConstraintList *constraints = nullptr);
|
||||
|
||||
HashNumber valueHash() const MOZ_OVERRIDE;
|
||||
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE;
|
||||
|
@ -2197,7 +2197,7 @@ class MParameter : public MNullaryInstruction
|
|||
public:
|
||||
static const int32_t THIS_SLOT = -1;
|
||||
|
||||
MParameter(int32_t index, types::TemporaryTypeSet *types)
|
||||
MParameter(int32_t index, TemporaryTypeSet *types)
|
||||
: index_(index)
|
||||
{
|
||||
setResultType(MIRType_Value);
|
||||
|
@ -2206,7 +2206,7 @@ class MParameter : public MNullaryInstruction
|
|||
|
||||
public:
|
||||
INSTRUCTION_HEADER(Parameter)
|
||||
static MParameter *New(TempAllocator &alloc, int32_t index, types::TemporaryTypeSet *types);
|
||||
static MParameter *New(TempAllocator &alloc, int32_t index, TemporaryTypeSet *types);
|
||||
|
||||
int32_t index() const {
|
||||
return index_;
|
||||
|
@ -2540,7 +2540,7 @@ class MTest
|
|||
// background threads. So make callers explicitly call it if they want us
|
||||
// to check whether the operand might do this. If this method is never
|
||||
// called, we'll assume our operand can emulate undefined.
|
||||
void cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints);
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
|
||||
bool *filtersNull);
|
||||
|
@ -2632,12 +2632,12 @@ class MThrow
|
|||
};
|
||||
|
||||
// Fabricate a type set containing only the type of the specified object.
|
||||
types::TemporaryTypeSet *
|
||||
MakeSingletonTypeSet(types::CompilerConstraintList *constraints, JSObject *obj);
|
||||
TemporaryTypeSet *
|
||||
MakeSingletonTypeSet(CompilerConstraintList *constraints, JSObject *obj);
|
||||
|
||||
bool
|
||||
MergeTypes(MIRType *ptype, types::TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, types::TemporaryTypeSet *newTypeSet);
|
||||
MergeTypes(MIRType *ptype, TemporaryTypeSet **ptypeSet,
|
||||
MIRType newType, TemporaryTypeSet *newTypeSet);
|
||||
|
||||
// Helper class to assert all GC pointers embedded in MIR instructions are
|
||||
// tenured. Off-thread Ion compilation and nursery GCs can happen in parallel,
|
||||
|
@ -2689,7 +2689,7 @@ class MNewArray
|
|||
// Allocate space at initialization or not
|
||||
AllocatingBehaviour allocating_;
|
||||
|
||||
MNewArray(types::CompilerConstraintList *constraints, uint32_t count, MConstant *templateConst,
|
||||
MNewArray(CompilerConstraintList *constraints, uint32_t count, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, AllocatingBehaviour allocating)
|
||||
: MUnaryInstruction(templateConst),
|
||||
count_(count),
|
||||
|
@ -2705,7 +2705,7 @@ class MNewArray
|
|||
public:
|
||||
INSTRUCTION_HEADER(NewArray)
|
||||
|
||||
static MNewArray *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewArray *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
uint32_t count, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, AllocatingBehaviour allocating)
|
||||
{
|
||||
|
@ -2755,7 +2755,7 @@ class MNewArrayCopyOnWrite : public MNullaryInstruction
|
|||
AlwaysTenured<ArrayObject*> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewArrayCopyOnWrite(types::CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
MNewArrayCopyOnWrite(CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
: templateObject_(templateObject),
|
||||
initialHeap_(initialHeap)
|
||||
|
@ -2769,7 +2769,7 @@ class MNewArrayCopyOnWrite : public MNullaryInstruction
|
|||
INSTRUCTION_HEADER(NewArrayCopyOnWrite)
|
||||
|
||||
static MNewArrayCopyOnWrite *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
|
@ -2796,7 +2796,7 @@ class MNewArrayDynamicLength
|
|||
AlwaysTenured<ArrayObject*> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewArrayDynamicLength(types::CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
MNewArrayDynamicLength(CompilerConstraintList *constraints, ArrayObject *templateObject,
|
||||
gc::InitialHeap initialHeap, MDefinition *length)
|
||||
: MUnaryInstruction(length),
|
||||
templateObject_(templateObject),
|
||||
|
@ -2811,7 +2811,7 @@ class MNewArrayDynamicLength
|
|||
public:
|
||||
INSTRUCTION_HEADER(NewArrayDynamicLength)
|
||||
|
||||
static MNewArrayDynamicLength *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewArrayDynamicLength *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
ArrayObject *templateObject, gc::InitialHeap initialHeap,
|
||||
MDefinition *length)
|
||||
{
|
||||
|
@ -2844,7 +2844,7 @@ class MNewObject
|
|||
gc::InitialHeap initialHeap_;
|
||||
Mode mode_;
|
||||
|
||||
MNewObject(types::CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
MNewObject(CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap, Mode mode)
|
||||
: MUnaryInstruction(templateConst),
|
||||
initialHeap_(initialHeap),
|
||||
|
@ -2867,7 +2867,7 @@ class MNewObject
|
|||
public:
|
||||
INSTRUCTION_HEADER(NewObject)
|
||||
|
||||
static MNewObject *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MNewObject *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MConstant *templateConst, gc::InitialHeap initialHeap,
|
||||
Mode mode)
|
||||
{
|
||||
|
@ -2903,7 +2903,7 @@ class MNewTypedObject : public MNullaryInstruction
|
|||
AlwaysTenured<InlineTypedObject *> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MNewTypedObject(types::CompilerConstraintList *constraints,
|
||||
MNewTypedObject(CompilerConstraintList *constraints,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
: templateObject_(templateObject),
|
||||
|
@ -2917,7 +2917,7 @@ class MNewTypedObject : public MNullaryInstruction
|
|||
INSTRUCTION_HEADER(NewTypedObject)
|
||||
|
||||
static MNewTypedObject *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
|
@ -2978,7 +2978,7 @@ class MSimdBox
|
|||
AlwaysTenured<InlineTypedObject *> templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MSimdBox(types::CompilerConstraintList *constraints,
|
||||
MSimdBox(CompilerConstraintList *constraints,
|
||||
MDefinition *op,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
|
@ -2996,7 +2996,7 @@ class MSimdBox
|
|||
INSTRUCTION_HEADER(SimdBox)
|
||||
|
||||
static MSimdBox *New(TempAllocator &alloc,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *op,
|
||||
InlineTypedObject *templateObject,
|
||||
gc::InitialHeap initialHeap)
|
||||
|
@ -3910,7 +3910,7 @@ class MCompare
|
|||
void filtersUndefinedOrNull(bool trueBranch, MDefinition **subject, bool *filtersUndefined,
|
||||
bool *filtersNull);
|
||||
|
||||
void infer(types::CompilerConstraintList *constraints,
|
||||
void infer(CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, jsbytecode *pc);
|
||||
CompareType compareType() const {
|
||||
return compareType_;
|
||||
|
@ -4002,10 +4002,10 @@ class MBox
|
|||
if (ins->resultTypeSet()) {
|
||||
setResultTypeSet(ins->resultTypeSet());
|
||||
} else if (ins->type() != MIRType_Value) {
|
||||
types::Type ntype = ins->type() == MIRType_Object
|
||||
? types::Type::AnyObjectType()
|
||||
: types::Type::PrimitiveType(ValueTypeFromMIRType(ins->type()));
|
||||
setResultTypeSet(alloc.lifoAlloc()->new_<types::TemporaryTypeSet>(alloc.lifoAlloc(), ntype));
|
||||
TypeSet::Type ntype = ins->type() == MIRType_Object
|
||||
? TypeSet::AnyObjectType()
|
||||
: TypeSet::PrimitiveType(ValueTypeFromMIRType(ins->type()));
|
||||
setResultTypeSet(alloc.lifoAlloc()->new_<TemporaryTypeSet>(alloc.lifoAlloc(), ntype));
|
||||
}
|
||||
setMovable();
|
||||
}
|
||||
|
@ -4261,7 +4261,7 @@ class MCreateThisWithTemplate
|
|||
{
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MCreateThisWithTemplate(types::CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
MCreateThisWithTemplate(CompilerConstraintList *constraints, MConstant *templateConst,
|
||||
gc::InitialHeap initialHeap)
|
||||
: MUnaryInstruction(templateConst),
|
||||
initialHeap_(initialHeap)
|
||||
|
@ -4272,7 +4272,7 @@ class MCreateThisWithTemplate
|
|||
|
||||
public:
|
||||
INSTRUCTION_HEADER(CreateThisWithTemplate)
|
||||
static MCreateThisWithTemplate *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MCreateThisWithTemplate *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MConstant *templateConst, gc::InitialHeap initialHeap)
|
||||
{
|
||||
return new(alloc) MCreateThisWithTemplate(constraints, templateConst, initialHeap);
|
||||
|
@ -4971,7 +4971,7 @@ class MTypeOf
|
|||
}
|
||||
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
void cacheInputMaybeCallableOrEmulatesUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheInputMaybeCallableOrEmulatesUndefined(CompilerConstraintList *constraints);
|
||||
|
||||
bool inputMaybeCallableOrEmulatesUndefined() const {
|
||||
return inputMaybeCallableOrEmulatesUndefined_;
|
||||
|
@ -6293,7 +6293,7 @@ class MStringSplit
|
|||
: public MTernaryInstruction,
|
||||
public MixPolicy<StringPolicy<0>, StringPolicy<1> >::Data
|
||||
{
|
||||
MStringSplit(types::CompilerConstraintList *constraints, MDefinition *string, MDefinition *sep,
|
||||
MStringSplit(CompilerConstraintList *constraints, MDefinition *string, MDefinition *sep,
|
||||
MConstant *templateObject)
|
||||
: MTernaryInstruction(string, sep, templateObject)
|
||||
{
|
||||
|
@ -6304,7 +6304,7 @@ class MStringSplit
|
|||
public:
|
||||
INSTRUCTION_HEADER(StringSplit)
|
||||
|
||||
static MStringSplit *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MStringSplit *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *string, MDefinition *sep,
|
||||
MConstant *templateObject)
|
||||
{
|
||||
|
@ -6504,7 +6504,7 @@ class MPhi MOZ_FINAL
|
|||
|
||||
// Add types for this phi which speculate about new inputs that may come in
|
||||
// via a loop backedge.
|
||||
bool addBackedgeType(MIRType type, types::TemporaryTypeSet *typeSet);
|
||||
bool addBackedgeType(MIRType type, TemporaryTypeSet *typeSet);
|
||||
|
||||
// Initializes the operands vector to the given capacity,
|
||||
// permitting use of addInput() instead of addInputSlow().
|
||||
|
@ -6904,7 +6904,7 @@ class MRegExp : public MNullaryInstruction
|
|||
AlwaysTenured<RegExpObject *> source_;
|
||||
bool mustClone_;
|
||||
|
||||
MRegExp(types::CompilerConstraintList *constraints, RegExpObject *source, bool mustClone)
|
||||
MRegExp(CompilerConstraintList *constraints, RegExpObject *source, bool mustClone)
|
||||
: source_(source),
|
||||
mustClone_(mustClone)
|
||||
{
|
||||
|
@ -6915,7 +6915,7 @@ class MRegExp : public MNullaryInstruction
|
|||
public:
|
||||
INSTRUCTION_HEADER(RegExp)
|
||||
|
||||
static MRegExp *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MRegExp *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
RegExpObject *source, bool mustClone)
|
||||
{
|
||||
return new(alloc) MRegExp(constraints, source, mustClone);
|
||||
|
@ -7183,7 +7183,7 @@ class MLambda
|
|||
{
|
||||
LambdaFunctionInfo info_;
|
||||
|
||||
MLambda(types::CompilerConstraintList *constraints, MDefinition *scopeChain, MConstant *cst)
|
||||
MLambda(CompilerConstraintList *constraints, MDefinition *scopeChain, MConstant *cst)
|
||||
: MBinaryInstruction(scopeChain, cst), info_(&cst->value().toObject().as<JSFunction>())
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
|
@ -7194,7 +7194,7 @@ class MLambda
|
|||
public:
|
||||
INSTRUCTION_HEADER(Lambda)
|
||||
|
||||
static MLambda *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MLambda *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *scopeChain, MConstant *fun)
|
||||
{
|
||||
return new(alloc) MLambda(constraints, scopeChain, fun);
|
||||
|
@ -7220,7 +7220,7 @@ class MLambdaArrow
|
|||
{
|
||||
LambdaFunctionInfo info_;
|
||||
|
||||
MLambdaArrow(types::CompilerConstraintList *constraints, MDefinition *scopeChain,
|
||||
MLambdaArrow(CompilerConstraintList *constraints, MDefinition *scopeChain,
|
||||
MDefinition *this_, JSFunction *fun)
|
||||
: MBinaryInstruction(scopeChain, this_), info_(fun)
|
||||
{
|
||||
|
@ -7233,7 +7233,7 @@ class MLambdaArrow
|
|||
public:
|
||||
INSTRUCTION_HEADER(LambdaArrow)
|
||||
|
||||
static MLambdaArrow *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MLambdaArrow *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *scopeChain, MDefinition *this_, JSFunction *fun)
|
||||
{
|
||||
return new(alloc) MLambdaArrow(constraints, scopeChain, this_, fun);
|
||||
|
@ -7773,7 +7773,7 @@ class MNot
|
|||
|
||||
INSTRUCTION_HEADER(Not)
|
||||
|
||||
void cacheOperandMightEmulateUndefined(types::CompilerConstraintList *constraints);
|
||||
void cacheOperandMightEmulateUndefined(CompilerConstraintList *constraints);
|
||||
MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
|
||||
void markOperandCantEmulateUndefined() {
|
||||
|
@ -8514,7 +8514,7 @@ class MArrayConcat
|
|||
AlwaysTenured<ArrayObject*> templateObj_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MArrayConcat(types::CompilerConstraintList *constraints, MDefinition *lhs, MDefinition *rhs,
|
||||
MArrayConcat(CompilerConstraintList *constraints, MDefinition *lhs, MDefinition *rhs,
|
||||
ArrayObject *templateObj, gc::InitialHeap initialHeap)
|
||||
: MBinaryInstruction(lhs, rhs),
|
||||
templateObj_(templateObj),
|
||||
|
@ -8527,7 +8527,7 @@ class MArrayConcat
|
|||
public:
|
||||
INSTRUCTION_HEADER(ArrayConcat)
|
||||
|
||||
static MArrayConcat *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MArrayConcat *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *lhs, MDefinition *rhs,
|
||||
ArrayObject *templateObj, gc::InitialHeap initialHeap)
|
||||
{
|
||||
|
@ -9251,7 +9251,7 @@ class InlinePropertyTable : public TempObject
|
|||
}
|
||||
|
||||
bool hasFunction(JSFunction *func) const;
|
||||
types::TemporaryTypeSet *buildTypeSetForFunction(JSFunction *func) const;
|
||||
TemporaryTypeSet *buildTypeSetForFunction(JSFunction *func) const;
|
||||
|
||||
// Remove targets that vetoed inlining from the InlinePropertyTable.
|
||||
void trimTo(ObjectVector &targets, BoolVector &choiceSet);
|
||||
|
@ -11319,7 +11319,7 @@ class MRest
|
|||
public MRestCommon,
|
||||
public IntPolicy<0>::Data
|
||||
{
|
||||
MRest(types::CompilerConstraintList *constraints, MDefinition *numActuals, unsigned numFormals,
|
||||
MRest(CompilerConstraintList *constraints, MDefinition *numActuals, unsigned numFormals,
|
||||
ArrayObject *templateObject)
|
||||
: MUnaryInstruction(numActuals),
|
||||
MRestCommon(numFormals, templateObject)
|
||||
|
@ -11331,7 +11331,7 @@ class MRest
|
|||
public:
|
||||
INSTRUCTION_HEADER(Rest)
|
||||
|
||||
static MRest *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
static MRest *New(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MDefinition *numActuals, unsigned numFormals,
|
||||
ArrayObject *templateObject)
|
||||
{
|
||||
|
@ -11354,7 +11354,7 @@ class MFilterTypeSet
|
|||
: public MUnaryInstruction,
|
||||
public FilterTypeSetPolicy::Data
|
||||
{
|
||||
MFilterTypeSet(MDefinition *def, types::TemporaryTypeSet *types)
|
||||
MFilterTypeSet(MDefinition *def, TemporaryTypeSet *types)
|
||||
: MUnaryInstruction(def)
|
||||
{
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
|
@ -11365,7 +11365,7 @@ class MFilterTypeSet
|
|||
public:
|
||||
INSTRUCTION_HEADER(FilterTypeSet)
|
||||
|
||||
static MFilterTypeSet *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types) {
|
||||
static MFilterTypeSet *New(TempAllocator &alloc, MDefinition *def, TemporaryTypeSet *types) {
|
||||
return new(alloc) MFilterTypeSet(def, types);
|
||||
}
|
||||
|
||||
|
@ -11388,7 +11388,7 @@ class MTypeBarrier
|
|||
{
|
||||
BarrierKind barrierKind_;
|
||||
|
||||
MTypeBarrier(MDefinition *def, types::TemporaryTypeSet *types, BarrierKind kind)
|
||||
MTypeBarrier(MDefinition *def, TemporaryTypeSet *types, BarrierKind kind)
|
||||
: MUnaryInstruction(def),
|
||||
barrierKind_(kind)
|
||||
{
|
||||
|
@ -11405,7 +11405,7 @@ class MTypeBarrier
|
|||
public:
|
||||
INSTRUCTION_HEADER(TypeBarrier)
|
||||
|
||||
static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, types::TemporaryTypeSet *types,
|
||||
static MTypeBarrier *New(TempAllocator &alloc, MDefinition *def, TemporaryTypeSet *types,
|
||||
BarrierKind kind = BarrierKind::TypeSet) {
|
||||
return new(alloc) MTypeBarrier(def, types, kind);
|
||||
}
|
||||
|
@ -11444,10 +11444,10 @@ class MMonitorTypes
|
|||
: public MUnaryInstruction,
|
||||
public BoxInputsPolicy::Data
|
||||
{
|
||||
const types::TemporaryTypeSet *typeSet_;
|
||||
const TemporaryTypeSet *typeSet_;
|
||||
BarrierKind barrierKind_;
|
||||
|
||||
MMonitorTypes(MDefinition *def, const types::TemporaryTypeSet *types, BarrierKind kind)
|
||||
MMonitorTypes(MDefinition *def, const TemporaryTypeSet *types, BarrierKind kind)
|
||||
: MUnaryInstruction(def),
|
||||
typeSet_(types),
|
||||
barrierKind_(kind)
|
||||
|
@ -11461,12 +11461,12 @@ class MMonitorTypes
|
|||
public:
|
||||
INSTRUCTION_HEADER(MonitorTypes)
|
||||
|
||||
static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const types::TemporaryTypeSet *types,
|
||||
static MMonitorTypes *New(TempAllocator &alloc, MDefinition *def, const TemporaryTypeSet *types,
|
||||
BarrierKind kind) {
|
||||
return new(alloc) MMonitorTypes(def, types, kind);
|
||||
}
|
||||
|
||||
const types::TemporaryTypeSet *typeSet() const {
|
||||
const TemporaryTypeSet *typeSet() const {
|
||||
return typeSet_;
|
||||
}
|
||||
BarrierKind barrierKind() const {
|
||||
|
@ -12701,35 +12701,35 @@ MControlInstruction *MDefinition::toControlInstruction() {
|
|||
|
||||
// Helper functions used to decide how to build MIR.
|
||||
|
||||
bool ElementAccessIsDenseNative(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsDenseNative(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id);
|
||||
bool ElementAccessIsAnyTypedArray(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsAnyTypedArray(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, MDefinition *id,
|
||||
Scalar::Type *arrayType);
|
||||
bool ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
|
||||
bool ElementAccessIsPacked(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessMightBeCopyOnWrite(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
bool ElementAccessHasExtraIndexedProperty(CompilerConstraintList *constraints,
|
||||
MDefinition *obj);
|
||||
MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
|
||||
MIRType DenseNativeElementType(CompilerConstraintList *constraints, MDefinition *obj);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
types::TypeSetObjectKey *key, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed, bool updateObserved);
|
||||
CompilerConstraintList *constraints,
|
||||
TypeSet::ObjectKey *key, PropertyName *name,
|
||||
TemporaryTypeSet *observed, bool updateObserved);
|
||||
BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
|
||||
types::CompilerConstraintList *constraints,
|
||||
CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *observed);
|
||||
BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name);
|
||||
void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
bool CanWriteProperty(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
types::HeapTypeSetKey property, MDefinition *value,
|
||||
TemporaryTypeSet *observed);
|
||||
bool CanWriteProperty(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
HeapTypeSetKey property, MDefinition *value,
|
||||
MIRType implicitType = MIRType_None);
|
||||
bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, MDefinition **pobj,
|
||||
PropertyName *name, MDefinition **pvalue,
|
||||
bool canModify, MIRType implicitType = MIRType_None);
|
||||
|
|
|
@ -37,17 +37,17 @@ namespace {
|
|||
// Emulate a TypeSet logic from a Type object to avoid duplicating the guard
|
||||
// logic.
|
||||
class TypeWrapper {
|
||||
types::Type t_;
|
||||
TypeSet::Type t_;
|
||||
|
||||
public:
|
||||
explicit TypeWrapper(types::Type t) : t_(t) {}
|
||||
explicit TypeWrapper(TypeSet::Type t) : t_(t) {}
|
||||
|
||||
inline bool unknown() const {
|
||||
return t_.isUnknown();
|
||||
}
|
||||
inline bool hasType(types::Type t) const {
|
||||
if (t == types::Type::Int32Type())
|
||||
return t == t_ || t_ == types::Type::DoubleType();
|
||||
inline bool hasType(TypeSet::Type t) const {
|
||||
if (t == TypeSet::Int32Type())
|
||||
return t == t_ || t_ == TypeSet::DoubleType();
|
||||
return t == t_;
|
||||
}
|
||||
inline unsigned getObjectCount() const {
|
||||
|
@ -69,30 +69,30 @@ class TypeWrapper {
|
|||
|
||||
} /* anonymous namespace */
|
||||
|
||||
template <typename Source, typename TypeSet> void
|
||||
MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, BarrierKind kind,
|
||||
template <typename Source, typename Set> void
|
||||
MacroAssembler::guardTypeSet(const Source &address, const Set *types, BarrierKind kind,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet);
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
|
||||
Label matched;
|
||||
types::Type tests[8] = {
|
||||
types::Type::Int32Type(),
|
||||
types::Type::UndefinedType(),
|
||||
types::Type::BooleanType(),
|
||||
types::Type::StringType(),
|
||||
types::Type::SymbolType(),
|
||||
types::Type::NullType(),
|
||||
types::Type::MagicArgType(),
|
||||
types::Type::AnyObjectType()
|
||||
TypeSet::Type tests[8] = {
|
||||
TypeSet::Int32Type(),
|
||||
TypeSet::UndefinedType(),
|
||||
TypeSet::BooleanType(),
|
||||
TypeSet::StringType(),
|
||||
TypeSet::SymbolType(),
|
||||
TypeSet::NullType(),
|
||||
TypeSet::MagicArgType(),
|
||||
TypeSet::AnyObjectType()
|
||||
};
|
||||
|
||||
// The double type also implies Int32.
|
||||
// So replace the int32 test with the double one.
|
||||
if (types->hasType(types::Type::DoubleType())) {
|
||||
MOZ_ASSERT(types->hasType(types::Type::Int32Type()));
|
||||
tests[0] = types::Type::DoubleType();
|
||||
if (types->hasType(TypeSet::DoubleType())) {
|
||||
MOZ_ASSERT(types->hasType(TypeSet::Int32Type()));
|
||||
tests[0] = TypeSet::DoubleType();
|
||||
}
|
||||
|
||||
Register tag = extractTag(address, scratch);
|
||||
|
@ -109,7 +109,7 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
|||
}
|
||||
|
||||
// If this is the last check, invert the last branch.
|
||||
if (types->hasType(types::Type::AnyObjectType()) || !types->getObjectCount()) {
|
||||
if (types->hasType(TypeSet::AnyObjectType()) || !types->getObjectCount()) {
|
||||
if (!lastBranch.isInitialized()) {
|
||||
jump(miss);
|
||||
return;
|
||||
|
@ -156,12 +156,12 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
|||
bind(&matched);
|
||||
}
|
||||
|
||||
template <typename TypeSet> void
|
||||
MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
template <typename Set> void
|
||||
MacroAssembler::guardObjectType(Register obj, const Set *types,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
MOZ_ASSERT(!types->unknown());
|
||||
MOZ_ASSERT(!types->hasType(types::Type::AnyObjectType()));
|
||||
MOZ_ASSERT(!types->hasType(TypeSet::AnyObjectType()));
|
||||
MOZ_ASSERT(types->getObjectCount());
|
||||
MOZ_ASSERT(scratch != InvalidReg);
|
||||
|
||||
|
@ -229,28 +229,28 @@ MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
|||
}
|
||||
|
||||
template <typename Source> void
|
||||
MacroAssembler::guardType(const Source &address, types::Type type,
|
||||
MacroAssembler::guardType(const Source &address, TypeSet::Type type,
|
||||
Register scratch, Label *miss)
|
||||
{
|
||||
TypeWrapper wrapper(type);
|
||||
guardTypeSet(address, &wrapper, BarrierKind::TypeSet, scratch, miss);
|
||||
}
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TemporaryTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TemporaryTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const TypedOrValueRegister ®, const types::HeapTypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const TypedOrValueRegister ®, const HeapTypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeSet *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardTypeSet(const Address &address, const TypeWrapper *types,
|
||||
|
@ -258,16 +258,16 @@ template void MacroAssembler::guardTypeSet(const Address &address, const TypeWra
|
|||
template void MacroAssembler::guardTypeSet(const ValueOperand &value, const TypeWrapper *types,
|
||||
BarrierKind kind, Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::TemporaryTypeSet *types,
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TemporaryTypeSet *types,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const types::TypeSet *types,
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TypeSet *types,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardObjectType(Register obj, const TypeWrapper *types,
|
||||
Register scratch, Label *miss);
|
||||
|
||||
template void MacroAssembler::guardType(const Address &address, types::Type type,
|
||||
template void MacroAssembler::guardType(const Address &address, TypeSet::Type type,
|
||||
Register scratch, Label *miss);
|
||||
template void MacroAssembler::guardType(const ValueOperand &value, types::Type type,
|
||||
template void MacroAssembler::guardType(const ValueOperand &value, TypeSet::Type type,
|
||||
Register scratch, Label *miss);
|
||||
|
||||
template<typename S, typename T>
|
||||
|
|
|
@ -118,20 +118,20 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
};
|
||||
|
||||
/*
|
||||
* Creates a branch based on a specific types::Type.
|
||||
* Note: emits number test (int/double) for types::Type::DoubleType()
|
||||
* Creates a branch based on a specific TypeSet::Type.
|
||||
* Note: emits number test (int/double) for TypeSet::DoubleType()
|
||||
*/
|
||||
class BranchType : public Branch
|
||||
{
|
||||
types::Type type_;
|
||||
TypeSet::Type type_;
|
||||
|
||||
public:
|
||||
BranchType()
|
||||
: Branch(),
|
||||
type_(types::Type::UnknownType())
|
||||
type_(TypeSet::UnknownType())
|
||||
{ }
|
||||
|
||||
BranchType(Condition cond, Register reg, types::Type type, Label *jump)
|
||||
BranchType(Condition cond, Register reg, TypeSet::Type type, Label *jump)
|
||||
: Branch(cond, reg, jump),
|
||||
type_(type)
|
||||
{ }
|
||||
|
@ -278,7 +278,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
template <typename TypeSet>
|
||||
void guardObjectType(Register obj, const TypeSet *types, Register scratch, Label *miss);
|
||||
template <typename Source>
|
||||
void guardType(const Source &address, types::Type type, Register scratch, Label *miss);
|
||||
void guardType(const Source &address, TypeSet::Type type, Register scratch, Label *miss);
|
||||
|
||||
void loadObjShape(Register objReg, Register dest) {
|
||||
loadPtr(Address(objReg, JSObject::offsetOfShape()), dest);
|
||||
|
|
|
@ -138,7 +138,7 @@ SpewTempOptimizationTypeInfoVector(const TempOptimizationTypeInfoVector *types,
|
|||
indent ? indent : "",
|
||||
TrackedTypeSiteString(t->site()), StringFromMIRType(t->mirType()));
|
||||
for (uint32_t i = 0; i < t->types().length(); i++)
|
||||
JitSpewCont(JitSpew_OptimizationTracking, " %s", types::TypeString(t->types()[i]));
|
||||
JitSpewCont(JitSpew_OptimizationTracking, " %s", TypeSet::TypeString(t->types()[i]));
|
||||
JitSpewFin(JitSpew_OptimizationTracking);
|
||||
}
|
||||
#endif
|
||||
|
@ -166,7 +166,7 @@ TrackedOptimizations::spew() const
|
|||
}
|
||||
|
||||
bool
|
||||
OptimizationTypeInfo::trackTypeSet(types::TemporaryTypeSet *typeSet)
|
||||
OptimizationTypeInfo::trackTypeSet(TemporaryTypeSet *typeSet)
|
||||
{
|
||||
if (!typeSet)
|
||||
return true;
|
||||
|
@ -174,7 +174,7 @@ OptimizationTypeInfo::trackTypeSet(types::TemporaryTypeSet *typeSet)
|
|||
}
|
||||
|
||||
bool
|
||||
OptimizationTypeInfo::trackType(types::Type type)
|
||||
OptimizationTypeInfo::trackType(TypeSet::Type type)
|
||||
{
|
||||
return types_.append(type);
|
||||
}
|
||||
|
@ -202,15 +202,15 @@ CombineHash(HashNumber h, HashNumber n)
|
|||
}
|
||||
|
||||
static inline HashNumber
|
||||
HashType(types::Type ty)
|
||||
HashType(TypeSet::Type ty)
|
||||
{
|
||||
if (ty.isObjectUnchecked())
|
||||
return PointerHasher<types::TypeSetObjectKey *, 3>::hash(ty.objectKey());
|
||||
return PointerHasher<TypeSet::ObjectKey *, 3>::hash(ty.objectKey());
|
||||
return HashNumber(ty.raw());
|
||||
}
|
||||
|
||||
static HashNumber
|
||||
HashTypeList(const types::TypeSet::TypeList &types)
|
||||
HashTypeList(const TypeSet::TypeList &types)
|
||||
{
|
||||
HashNumber h = 0;
|
||||
for (uint32_t i = 0; i < types.length(); i++)
|
||||
|
@ -348,18 +348,18 @@ class jit::UniqueTrackedTypes
|
|||
public:
|
||||
struct TypeHasher
|
||||
{
|
||||
typedef types::Type Lookup;
|
||||
typedef TypeSet::Type Lookup;
|
||||
|
||||
static HashNumber hash(const Lookup &ty) { return HashType(ty); }
|
||||
static bool match(const types::Type &ty1, const types::Type &ty2) { return ty1 == ty2; }
|
||||
static bool match(const TypeSet::Type &ty1, const TypeSet::Type &ty2) { return ty1 == ty2; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Map of unique types::Types to indices.
|
||||
typedef HashMap<types::Type, uint8_t, TypeHasher> TypesMap;
|
||||
// Map of unique TypeSet::Types to indices.
|
||||
typedef HashMap<TypeSet::Type, uint8_t, TypeHasher> TypesMap;
|
||||
TypesMap map_;
|
||||
|
||||
Vector<types::Type, 1> list_;
|
||||
Vector<TypeSet::Type, 1> list_;
|
||||
|
||||
public:
|
||||
explicit UniqueTrackedTypes(JSContext *cx)
|
||||
|
@ -368,14 +368,14 @@ class jit::UniqueTrackedTypes
|
|||
{ }
|
||||
|
||||
bool init() { return map_.init(); }
|
||||
bool getIndexOf(types::Type ty, uint8_t *indexp);
|
||||
bool getIndexOf(TypeSet::Type ty, uint8_t *indexp);
|
||||
|
||||
uint32_t count() const { MOZ_ASSERT(map_.count() == list_.length()); return list_.length(); }
|
||||
bool enumerate(types::TypeSet::TypeList *types) const;
|
||||
bool enumerate(TypeSet::TypeList *types) const;
|
||||
};
|
||||
|
||||
bool
|
||||
UniqueTrackedTypes::getIndexOf(types::Type ty, uint8_t *indexp)
|
||||
UniqueTrackedTypes::getIndexOf(TypeSet::Type ty, uint8_t *indexp)
|
||||
{
|
||||
TypesMap::AddPtr p = map_.lookupForAdd(ty);
|
||||
if (p) {
|
||||
|
@ -398,7 +398,7 @@ UniqueTrackedTypes::getIndexOf(types::Type ty, uint8_t *indexp)
|
|||
}
|
||||
|
||||
bool
|
||||
UniqueTrackedTypes::enumerate(types::TypeSet::TypeList *types) const
|
||||
UniqueTrackedTypes::enumerate(TypeSet::TypeList *types) const
|
||||
{
|
||||
return types->append(list_.begin(), list_.end());
|
||||
}
|
||||
|
@ -814,19 +814,19 @@ WriteOffsetsTable(CompactBufferWriter &writer, const Vector<uint32_t, 16> &offse
|
|||
}
|
||||
|
||||
static JSFunction *
|
||||
MaybeConstructorFromType(types::Type ty)
|
||||
MaybeConstructorFromType(TypeSet::Type ty)
|
||||
{
|
||||
if (ty.isUnknown() || ty.isAnyObject() || !ty.isGroup())
|
||||
return nullptr;
|
||||
ObjectGroup *obj = ty.group();
|
||||
types::TypeNewScript *newScript = obj->newScript();
|
||||
TypeNewScript *newScript = obj->newScript();
|
||||
if (!newScript && obj->maybeUnboxedLayout())
|
||||
newScript = obj->unboxedLayout().newScript();
|
||||
return newScript ? newScript->function() : nullptr;
|
||||
}
|
||||
|
||||
static void
|
||||
SpewConstructor(types::Type ty, JSFunction *constructor)
|
||||
SpewConstructor(TypeSet::Type ty, JSFunction *constructor)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char buf[512];
|
||||
|
@ -843,16 +843,16 @@ SpewConstructor(types::Type ty, JSFunction *constructor)
|
|||
}
|
||||
|
||||
JitSpew(JitSpew_OptimizationTracking, " Unique type %s has constructor %s (%s:%u)",
|
||||
types::TypeString(ty), buf, filename, lineno);
|
||||
TypeSet::TypeString(ty), buf, filename, lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SpewAllocationSite(types::Type ty, JSScript *script, uint32_t offset)
|
||||
SpewAllocationSite(TypeSet::Type ty, JSScript *script, uint32_t offset)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JitSpew(JitSpew_OptimizationTracking, " Unique type %s has alloc site %s:%u",
|
||||
types::TypeString(ty), script->filename(),
|
||||
TypeSet::TypeString(ty), script->filename(),
|
||||
PCToLineNumber(script, script->offsetToPC(offset)));
|
||||
#endif
|
||||
}
|
||||
|
@ -942,11 +942,11 @@ jit::WriteIonTrackedOptimizationsTable(JSContext *cx, CompactBufferWriter &write
|
|||
// instead of during profiling to avoid touching compartment tables during
|
||||
// profiling. Additionally, TypeNewScript is subject to GC in the
|
||||
// meantime.
|
||||
types::TypeSet::TypeList uniqueTypeList;
|
||||
TypeSet::TypeList uniqueTypeList;
|
||||
if (!uniqueTypes.enumerate(&uniqueTypeList))
|
||||
return false;
|
||||
for (uint32_t i = 0; i < uniqueTypeList.length(); i++) {
|
||||
types::Type ty = uniqueTypeList[i];
|
||||
TypeSet::Type ty = uniqueTypeList[i];
|
||||
if (JSFunction *constructor = MaybeConstructorFromType(ty)) {
|
||||
if (!allTypes->append(IonTrackedTypeWithAddendum(ty, constructor)))
|
||||
return false;
|
||||
|
@ -954,7 +954,9 @@ jit::WriteIonTrackedOptimizationsTable(JSContext *cx, CompactBufferWriter &write
|
|||
} else {
|
||||
JSScript *script;
|
||||
uint32_t offset;
|
||||
if (ObjectGroup::findAllocationSiteForType(cx, ty, &script, &offset)) {
|
||||
if (!ty.isUnknown() && !ty.isAnyObject() && ty.isGroup() &&
|
||||
ObjectGroup::findAllocationSite(cx, ty.group(), &script, &offset))
|
||||
{
|
||||
if (!allTypes->append(IonTrackedTypeWithAddendum(ty, script, offset)))
|
||||
return false;
|
||||
SpewAllocationSite(ty, script, offset);
|
||||
|
@ -1032,7 +1034,7 @@ IonBuilder::startTrackingOptimizations()
|
|||
|
||||
void
|
||||
IonBuilder::trackTypeInfoUnchecked(TrackedTypeSite kind, MIRType mirType,
|
||||
types::TemporaryTypeSet *typeSet)
|
||||
TemporaryTypeSet *typeSet)
|
||||
{
|
||||
BytecodeSite *site = current->trackedSite();
|
||||
// OOMs are handled as if optimization tracking were turned off.
|
||||
|
@ -1051,7 +1053,7 @@ IonBuilder::trackTypeInfoUnchecked(TrackedTypeSite kind, JSObject *obj)
|
|||
BytecodeSite *site = current->trackedSite();
|
||||
// OOMs are handled as if optimization tracking were turned off.
|
||||
OptimizationTypeInfo typeInfo(kind, MIRType_Object);
|
||||
if (!typeInfo.trackType(types::Type::ObjectType(obj)))
|
||||
if (!typeInfo.trackType(TypeSet::ObjectType(obj)))
|
||||
return;
|
||||
if (!site->optimizations()->trackTypeInfo(mozilla::Move(typeInfo)))
|
||||
site->setOptimizations(nullptr);
|
||||
|
@ -1068,7 +1070,7 @@ IonBuilder::trackTypeInfoUnchecked(CallInfo &callInfo)
|
|||
trackTypeInfoUnchecked(TrackedTypeSite::Call_Arg, arg->type(), arg->resultTypeSet());
|
||||
}
|
||||
|
||||
types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||
trackTypeInfoUnchecked(TrackedTypeSite::Call_Return, returnTypes->getKnownMIRType(),
|
||||
returnTypes);
|
||||
}
|
||||
|
@ -1140,7 +1142,7 @@ InterpretedFunctionFromTrackedType(const IonTrackedTypeWithAddendum &tracked)
|
|||
if (tracked.hasConstructor())
|
||||
return tracked.constructor;
|
||||
|
||||
types::Type ty = tracked.type;
|
||||
TypeSet::Type ty = tracked.type;
|
||||
|
||||
if (ty.isSingleton()) {
|
||||
JSObject *obj = ty.singleton();
|
||||
|
@ -1162,10 +1164,10 @@ class ForEachTypeInfoAdapter : public IonTrackedOptimizationsTypeInfo::ForEachOp
|
|||
{ }
|
||||
|
||||
void readType(const IonTrackedTypeWithAddendum &tracked) MOZ_OVERRIDE {
|
||||
types::Type ty = tracked.type;
|
||||
TypeSet::Type ty = tracked.type;
|
||||
|
||||
if (ty.isPrimitive() || ty.isUnknown() || ty.isAnyObject()) {
|
||||
op_.readType("primitive", types::NonObjectTypeString(ty), nullptr, 0);
|
||||
op_.readType("primitive", TypeSet::NonObjectTypeString(ty), nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class OptimizationTypeInfo
|
|||
{
|
||||
JS::TrackedTypeSite site_;
|
||||
MIRType mirType_;
|
||||
types::TypeSet::TypeList types_;
|
||||
TypeSet::TypeList types_;
|
||||
|
||||
public:
|
||||
OptimizationTypeInfo(OptimizationTypeInfo &&other)
|
||||
|
@ -73,12 +73,12 @@ class OptimizationTypeInfo
|
|||
mirType_(mirType)
|
||||
{ }
|
||||
|
||||
bool trackTypeSet(types::TemporaryTypeSet *typeSet);
|
||||
bool trackType(types::Type type);
|
||||
bool trackTypeSet(TemporaryTypeSet *typeSet);
|
||||
bool trackType(TypeSet::Type type);
|
||||
|
||||
JS::TrackedTypeSite site() const { return site_; }
|
||||
MIRType mirType() const { return mirType_; }
|
||||
const types::TypeSet::TypeList &types() const { return types_; }
|
||||
const TypeSet::TypeList &types() const { return types_; }
|
||||
|
||||
bool operator ==(const OptimizationTypeInfo &other) const;
|
||||
bool operator !=(const OptimizationTypeInfo &other) const;
|
||||
|
@ -421,7 +421,7 @@ class IonTrackedOptimizationsAttempts
|
|||
|
||||
struct IonTrackedTypeWithAddendum
|
||||
{
|
||||
types::Type type;
|
||||
TypeSet::Type type;
|
||||
|
||||
enum HasAddendum {
|
||||
HasNothing,
|
||||
|
@ -441,19 +441,19 @@ struct IonTrackedTypeWithAddendum
|
|||
JSFunction *constructor;
|
||||
};
|
||||
|
||||
explicit IonTrackedTypeWithAddendum(types::Type type)
|
||||
explicit IonTrackedTypeWithAddendum(TypeSet::Type type)
|
||||
: type(type),
|
||||
hasAddendum(HasNothing)
|
||||
{ }
|
||||
|
||||
IonTrackedTypeWithAddendum(types::Type type, JSScript *script, uint32_t offset)
|
||||
IonTrackedTypeWithAddendum(TypeSet::Type type, JSScript *script, uint32_t offset)
|
||||
: type(type),
|
||||
hasAddendum(HasAllocationSite),
|
||||
script(script),
|
||||
offset(offset)
|
||||
{ }
|
||||
|
||||
IonTrackedTypeWithAddendum(types::Type type, JSFunction *constructor)
|
||||
IonTrackedTypeWithAddendum(TypeSet::Type type, JSFunction *constructor)
|
||||
: type(type),
|
||||
hasAddendum(HasConstructor),
|
||||
constructor(constructor)
|
||||
|
@ -482,7 +482,7 @@ class IonTrackedOptimizationsTypeInfo
|
|||
// Unlike IonTrackedOptimizationAttempts,
|
||||
// JS::ForEachTrackedOptimizaitonTypeInfoOp cannot be used directly. The
|
||||
// internal API needs to deal with engine-internal data structures (e.g.,
|
||||
// types::Type) directly.
|
||||
// TypeSet::Type) directly.
|
||||
struct ForEachOp
|
||||
{
|
||||
virtual void readType(const IonTrackedTypeWithAddendum &tracked) = 0;
|
||||
|
|
|
@ -99,7 +99,7 @@ InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Val
|
|||
if (obj->is<JSFunction>()) {
|
||||
jsbytecode *pc;
|
||||
RootedScript script(cx, cx->currentScript(&pc));
|
||||
types::TypeScript::Monitor(cx, script, pc, rv.get());
|
||||
TypeScript::Monitor(cx, script, pc, rv.get());
|
||||
}
|
||||
|
||||
*rval = rv;
|
||||
|
@ -330,7 +330,7 @@ ArrayPopDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
|
|||
// have to monitor the return value.
|
||||
rval.set(argv[0]);
|
||||
if (rval.isUndefined())
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,7 @@ ArrayShiftDense(JSContext *cx, HandleObject obj, MutableHandleValue rval)
|
|||
// have to monitor the return value.
|
||||
rval.set(argv[0]);
|
||||
if (rval.isUndefined())
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -583,7 +583,7 @@ GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rva
|
|||
// purposes, as its side effect is not observable from JS. We are
|
||||
// guaranteed to bail out after this function, but because of its AliasSet,
|
||||
// type info will not be reflowed. Manually monitor here.
|
||||
types::TypeScript::Monitor(cx, rval);
|
||||
TypeScript::Monitor(cx, rval);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -874,7 +874,7 @@ class ReadTempAttemptsVectorOp : public JS::ForEachTrackedOptimizationAttemptOp
|
|||
struct ReadTempTypeInfoVectorOp : public IonTrackedOptimizationsTypeInfo::ForEachOp
|
||||
{
|
||||
TempOptimizationTypeInfoVector *types_;
|
||||
types::TypeSet::TypeList accTypes_;
|
||||
TypeSet::TypeList accTypes_;
|
||||
|
||||
public:
|
||||
explicit ReadTempTypeInfoVectorOp(TempOptimizationTypeInfoVector *types)
|
||||
|
|
|
@ -97,7 +97,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::PodCopy;
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Abs;
|
||||
using mozilla::ArrayLength;
|
||||
|
@ -1225,8 +1224,7 @@ InitArrayTypes(JSContext *cx, ObjectGroup *group, const Value *vector, unsigned
|
|||
for (unsigned i = 0; i < count; i++) {
|
||||
if (vector[i].isMagic(JS_ELEMENTS_HOLE))
|
||||
continue;
|
||||
Type valtype = GetValueType(vector[i]);
|
||||
types->addType(cx, valtype);
|
||||
types->addType(cx, TypeSet::GetValueType(vector[i]));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "vm/BooleanObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
const Class BooleanObject::class_ = {
|
||||
"Boolean",
|
||||
|
|
|
@ -253,7 +253,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode)
|
|||
* This printing depends on atoms still existing.
|
||||
*/
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
types::PrintTypes(cx, c, false);
|
||||
PrintTypes(cx, c, false);
|
||||
}
|
||||
if (mode == DCM_FORCE_GC) {
|
||||
MOZ_ASSERT(!rt->isHeapBusy());
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::IsFinite;
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::PodArrayZero;
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
using namespace js::frontend;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
|
|
|
@ -2218,7 +2218,7 @@ GCRuntime::sweepTypesAfterCompacting(Zone *zone)
|
|||
FreeOp *fop = rt->defaultFreeOp();
|
||||
zone->beginSweepTypes(fop, rt->gc.releaseObservedTypes && !zone->isPreservingCode());
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(zone);
|
||||
AutoClearTypeInferenceStateOnOOM oom(zone);
|
||||
|
||||
for (ZoneCellIterUnderGC i(zone, FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
|
@ -5191,13 +5191,13 @@ SweepThing(Shape *shape)
|
|||
}
|
||||
|
||||
static void
|
||||
SweepThing(JSScript *script, types::AutoClearTypeInferenceStateOnOOM *oom)
|
||||
SweepThing(JSScript *script, AutoClearTypeInferenceStateOnOOM *oom)
|
||||
{
|
||||
script->maybeSweepTypes(oom);
|
||||
}
|
||||
|
||||
static void
|
||||
SweepThing(ObjectGroup *group, types::AutoClearTypeInferenceStateOnOOM *oom)
|
||||
SweepThing(ObjectGroup *group, AutoClearTypeInferenceStateOnOOM *oom)
|
||||
{
|
||||
group->maybeSweep(oom);
|
||||
}
|
||||
|
@ -5245,7 +5245,7 @@ GCRuntime::sweepPhase(SliceBudget &sliceBudget)
|
|||
for (; sweepZone; sweepZone = sweepZone->nextNodeInGroup()) {
|
||||
ArenaLists &al = sweepZone->arenas;
|
||||
|
||||
types::AutoClearTypeInferenceStateOnOOM oom(sweepZone);
|
||||
AutoClearTypeInferenceStateOnOOM oom(sweepZone);
|
||||
|
||||
if (!SweepArenaList<JSScript>(&al.gcScriptArenasToUpdate, sliceBudget, &oom))
|
||||
return NotFinished;
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
|
@ -76,7 +75,7 @@ id_caller(JSContext *cx)
|
|||
}
|
||||
|
||||
const char *
|
||||
types::TypeIdStringImpl(jsid id)
|
||||
js::TypeIdStringImpl(jsid id)
|
||||
{
|
||||
if (JSID_IS_VOID(id))
|
||||
return "(index)";
|
||||
|
@ -97,8 +96,8 @@ types::TypeIdStringImpl(jsid id)
|
|||
// Logging
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *
|
||||
types::NonObjectTypeString(Type type)
|
||||
/* static */ const char *
|
||||
TypeSet::NonObjectTypeString(TypeSet::Type type)
|
||||
{
|
||||
if (type.isPrimitive()) {
|
||||
switch (type.primitive()) {
|
||||
|
@ -170,7 +169,7 @@ static bool InferSpewColorable()
|
|||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColorReset()
|
||||
js::InferSpewColorReset()
|
||||
{
|
||||
if (!InferSpewColorable())
|
||||
return "";
|
||||
|
@ -178,7 +177,7 @@ types::InferSpewColorReset()
|
|||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColor(TypeConstraint *constraint)
|
||||
js::InferSpewColor(TypeConstraint *constraint)
|
||||
{
|
||||
/* Type constraints are printed out using foreground colors. */
|
||||
static const char * const colors[] = { "\x1b[31m", "\x1b[32m", "\x1b[33m",
|
||||
|
@ -190,7 +189,7 @@ types::InferSpewColor(TypeConstraint *constraint)
|
|||
}
|
||||
|
||||
const char *
|
||||
types::InferSpewColor(TypeSet *types)
|
||||
js::InferSpewColor(TypeSet *types)
|
||||
{
|
||||
/* Type sets are printed out using bold colors. */
|
||||
static const char * const colors[] = { "\x1b[1;31m", "\x1b[1;32m", "\x1b[1;33m",
|
||||
|
@ -201,8 +200,8 @@ types::InferSpewColor(TypeSet *types)
|
|||
return colors[DefaultHasher<TypeSet *>::hash(types) % 7];
|
||||
}
|
||||
|
||||
const char *
|
||||
types::TypeString(Type type)
|
||||
/* static */ const char *
|
||||
TypeSet::TypeString(TypeSet::Type type)
|
||||
{
|
||||
if (type.isPrimitive() || type.isUnknown() || type.isAnyObject())
|
||||
return NonObjectTypeString(type);
|
||||
|
@ -219,14 +218,14 @@ types::TypeString(Type type)
|
|||
return bufs[which];
|
||||
}
|
||||
|
||||
const char *
|
||||
types::ObjectGroupString(ObjectGroup *group)
|
||||
/* static */ const char *
|
||||
TypeSet::ObjectGroupString(ObjectGroup *group)
|
||||
{
|
||||
return TypeString(Type::ObjectType(group));
|
||||
return TypeString(TypeSet::ObjectType(group));
|
||||
}
|
||||
|
||||
void
|
||||
types::InferSpew(SpewChannel channel, const char *fmt, ...)
|
||||
js::InferSpew(SpewChannel channel, const char *fmt, ...)
|
||||
{
|
||||
if (!InferSpewActive(channel))
|
||||
return;
|
||||
|
@ -240,7 +239,7 @@ types::InferSpew(SpewChannel channel, const char *fmt, ...)
|
|||
}
|
||||
|
||||
bool
|
||||
types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
js::ObjectGroupHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
{
|
||||
/*
|
||||
* Check the correctness of the type information in the object's property
|
||||
|
@ -253,7 +252,7 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
|||
if (id == id___proto__(cx) || id == id_constructor(cx) || id == id_caller(cx))
|
||||
return true;
|
||||
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
|
||||
// Type set guards might miss when an object's group changes and its
|
||||
// properties become unknown.
|
||||
|
@ -277,7 +276,8 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
|||
|
||||
if (!types->hasType(type)) {
|
||||
TypeFailure(cx, "Missing type in object %s %s: %s",
|
||||
ObjectGroupString(group), TypeIdString(id), TypeString(type));
|
||||
TypeSet::ObjectGroupString(group), TypeIdString(id),
|
||||
TypeSet::TypeString(type));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -286,7 +286,7 @@ types::TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &
|
|||
#endif
|
||||
|
||||
void
|
||||
types::TypeFailure(JSContext *cx, const char *fmt, ...)
|
||||
js::TypeFailure(JSContext *cx, const char *fmt, ...)
|
||||
{
|
||||
char msgbuf[1024]; /* Larger error messages will be truncated */
|
||||
char errbuf[1024];
|
||||
|
@ -323,12 +323,12 @@ TemporaryTypeSet::TemporaryTypeSet(LifoAlloc *alloc, Type type)
|
|||
flags |= TYPE_FLAG_ANYOBJECT;
|
||||
} else {
|
||||
setBaseObjectCount(1);
|
||||
objectSet = reinterpret_cast<TypeSetObjectKey**>(type.objectKey());
|
||||
objectSet = reinterpret_cast<ObjectKey**>(type.objectKey());
|
||||
|
||||
if (type.isGroup()) {
|
||||
ObjectGroup *ngroup = type.group();
|
||||
if (ngroup->newScript() && ngroup->newScript()->initializedGroup())
|
||||
addType(Type::ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
addType(ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -387,10 +387,10 @@ TypeSet::objectsAreSubset(TypeSet *other)
|
|||
return false;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(key)))
|
||||
if (!other->hasType(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -407,10 +407,10 @@ TypeSet::isSubset(const TypeSet *other) const
|
|||
MOZ_ASSERT(other->unknownObject());
|
||||
} else {
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (!other->hasType(Type::ObjectType(key)))
|
||||
if (!other->hasType(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -423,12 +423,12 @@ TypeSet::enumerateTypes(TypeList *list) const
|
|||
{
|
||||
/* If any type is possible, there's no need to worry about specifics. */
|
||||
if (flags & TYPE_FLAG_UNKNOWN)
|
||||
return list->append(Type::UnknownType());
|
||||
return list->append(UnknownType());
|
||||
|
||||
/* Enqueue type set members stored as bits. */
|
||||
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
|
||||
if (flags & flag) {
|
||||
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
|
||||
Type type = PrimitiveType(TypeFlagPrimitive(flag));
|
||||
if (!list->append(type))
|
||||
return false;
|
||||
}
|
||||
|
@ -436,14 +436,14 @@ TypeSet::enumerateTypes(TypeList *list) const
|
|||
|
||||
/* If any object is possible, skip specifics. */
|
||||
if (flags & TYPE_FLAG_ANYOBJECT)
|
||||
return list->append(Type::AnyObjectType());
|
||||
return list->append(AnyObjectType());
|
||||
|
||||
/* Enqueue specific object types. */
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key) {
|
||||
if (!list->append(Type::ObjectType(key)))
|
||||
if (!list->append(ObjectType(key)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -532,8 +532,8 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
|||
|
||||
{
|
||||
uint32_t objectCount = baseObjectCount();
|
||||
TypeSetObjectKey *key = type.objectKey();
|
||||
TypeSetObjectKey **pentry = HashSetInsert<TypeSetObjectKey *,TypeSetObjectKey,TypeSetObjectKey>
|
||||
ObjectKey *key = type.objectKey();
|
||||
ObjectKey **pentry = TypeHashSet::Insert<ObjectKey *, ObjectKey, ObjectKey>
|
||||
(*alloc, objectSet, objectCount, key);
|
||||
if (!pentry)
|
||||
goto unknownObject;
|
||||
|
@ -579,7 +579,7 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
|||
// corresponding fully initialized group, as an object's group may change
|
||||
// from the former to the latter via the acquired properties analysis.
|
||||
if (ngroup->newScript() && ngroup->newScript()->initializedGroup())
|
||||
addType(Type::ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
addType(ObjectType(ngroup->newScript()->initializedGroup()), alloc);
|
||||
}
|
||||
|
||||
if (false) {
|
||||
|
@ -600,7 +600,7 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
|
|||
TypeSet::addType(type, &cxArg->typeLifoAlloc());
|
||||
|
||||
if (type.isObjectUnchecked() && unknownObject())
|
||||
type = Type::AnyObjectType();
|
||||
type = AnyObjectType();
|
||||
|
||||
InferSpew(ISpewOps, "addType: %sT%p%s %s",
|
||||
InferSpewColor(this), this, InferSpewColorReset(),
|
||||
|
@ -663,9 +663,9 @@ TypeSet::print()
|
|||
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key)
|
||||
fprintf(stderr, " %s", TypeString(Type::ObjectType(key)));
|
||||
fprintf(stderr, " %s", TypeString(ObjectType(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -677,7 +677,7 @@ TypeSet::readBarrier(const TypeSet *types)
|
|||
return;
|
||||
|
||||
for (unsigned i = 0; i < types->getObjectCount(); i++) {
|
||||
if (TypeSetObjectKey *key = types->getObject(i)) {
|
||||
if (ObjectKey *key = types->getObject(i)) {
|
||||
if (key->isSingleton())
|
||||
(void) key->singleton();
|
||||
else
|
||||
|
@ -692,11 +692,11 @@ TypeSet::clone(LifoAlloc *alloc, TemporaryTypeSet *result) const
|
|||
MOZ_ASSERT(result->empty());
|
||||
|
||||
unsigned objectCount = baseObjectCount();
|
||||
unsigned capacity = (objectCount >= 2) ? HashSetCapacity(objectCount) : 0;
|
||||
unsigned capacity = (objectCount >= 2) ? TypeHashSet::Capacity(objectCount) : 0;
|
||||
|
||||
TypeSetObjectKey **newSet;
|
||||
ObjectKey **newSet;
|
||||
if (capacity) {
|
||||
newSet = alloc->newArray<TypeSetObjectKey*>(capacity);
|
||||
newSet = alloc->newArray<ObjectKey*>(capacity);
|
||||
if (!newSet)
|
||||
return false;
|
||||
PodCopy(newSet, objectSet, capacity);
|
||||
|
@ -759,18 +759,18 @@ TypeSet::cloneWithoutObjects(LifoAlloc *alloc)
|
|||
TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
|
||||
{
|
||||
TemporaryTypeSet *res = alloc->new_<TemporaryTypeSet>(a->baseFlags() | b->baseFlags(),
|
||||
static_cast<TypeSetObjectKey**>(nullptr));
|
||||
static_cast<ObjectKey**>(nullptr));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
if (!res->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount() && !res->unknownObject(); i++) {
|
||||
if (TypeSetObjectKey *key = a->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
if (ObjectKey *key = a->getObject(i))
|
||||
res->addType(ObjectType(key), alloc);
|
||||
}
|
||||
for (size_t i = 0; i < b->getObjectCount() && !res->unknownObject(); i++) {
|
||||
if (TypeSetObjectKey *key = b->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
if (ObjectKey *key = b->getObject(i))
|
||||
res->addType(ObjectType(key), alloc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -782,7 +782,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
|||
{
|
||||
TemporaryTypeSet *res;
|
||||
res = alloc->new_<TemporaryTypeSet>(a->baseFlags() & b->baseFlags(),
|
||||
static_cast<TypeSetObjectKey**>(nullptr));
|
||||
static_cast<ObjectKey**>(nullptr));
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
|
@ -795,7 +795,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
|||
if (a->unknownObject()) {
|
||||
for (size_t i = 0; i < b->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(b->getObject(i)), alloc);
|
||||
res->addType(ObjectType(b->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
|||
if (b->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount(); i++) {
|
||||
if (b->getObject(i))
|
||||
res->addType(Type::ObjectType(a->getObject(i)), alloc);
|
||||
res->addType(ObjectType(a->getObject(i)), alloc);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -816,7 +816,7 @@ TypeSet::intersectSets(TemporaryTypeSet *a, TemporaryTypeSet *b, LifoAlloc *allo
|
|||
continue;
|
||||
if (!b->getObject(j))
|
||||
continue;
|
||||
res->addType(Type::ObjectType(b->getObject(j)), alloc);
|
||||
res->addType(ObjectType(b->getObject(j)), alloc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +869,7 @@ class CompilerConstraint
|
|||
virtual bool generateTypeConstraint(JSContext *cx, RecompileInfo recompileInfo) = 0;
|
||||
};
|
||||
|
||||
class types::CompilerConstraintList
|
||||
class js::CompilerConstraintList
|
||||
{
|
||||
public:
|
||||
struct FrozenScript
|
||||
|
@ -949,7 +949,7 @@ class types::CompilerConstraintList
|
|||
};
|
||||
|
||||
CompilerConstraintList *
|
||||
types::NewCompilerConstraintList(jit::TempAllocator &alloc)
|
||||
js::NewCompilerConstraintList(jit::TempAllocator &alloc)
|
||||
{
|
||||
return alloc.lifoAlloc()->new_<CompilerConstraintList>(alloc);
|
||||
}
|
||||
|
@ -1015,7 +1015,7 @@ class TypeCompilerConstraint : public TypeConstraint
|
|||
|
||||
const char *kind() { return data.kind(); }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
if (data.invalidateOnNewType(type))
|
||||
cx->zone()->types.addPendingRecompile(cx, compilation);
|
||||
}
|
||||
|
@ -1061,19 +1061,19 @@ CompilerConstraintInstance<T>::generateTypeConstraint(JSContext *cx, RecompileIn
|
|||
} /* anonymous namespace */
|
||||
|
||||
const Class *
|
||||
TypeSetObjectKey::clasp()
|
||||
TypeSet::ObjectKey::clasp()
|
||||
{
|
||||
return isGroup() ? group()->clasp() : singleton()->getClass();
|
||||
}
|
||||
|
||||
TaggedProto
|
||||
TypeSetObjectKey::proto()
|
||||
TypeSet::ObjectKey::proto()
|
||||
{
|
||||
return isGroup() ? group()->proto() : singleton()->getTaggedProto();
|
||||
}
|
||||
|
||||
TypeNewScript *
|
||||
TypeSetObjectKey::newScript()
|
||||
TypeSet::ObjectKey::newScript()
|
||||
{
|
||||
if (isGroup() && group()->newScript())
|
||||
return group()->newScript();
|
||||
|
@ -1081,7 +1081,7 @@ TypeSetObjectKey::newScript()
|
|||
}
|
||||
|
||||
ObjectGroup *
|
||||
TypeSetObjectKey::maybeGroup()
|
||||
TypeSet::ObjectKey::maybeGroup()
|
||||
{
|
||||
if (isGroup())
|
||||
return group();
|
||||
|
@ -1091,7 +1091,7 @@ TypeSetObjectKey::maybeGroup()
|
|||
}
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::unknownProperties()
|
||||
TypeSet::ObjectKey::unknownProperties()
|
||||
{
|
||||
if (ObjectGroup *group = maybeGroup())
|
||||
return group->unknownProperties();
|
||||
|
@ -1099,7 +1099,7 @@ TypeSetObjectKey::unknownProperties()
|
|||
}
|
||||
|
||||
HeapTypeSetKey
|
||||
TypeSetObjectKey::property(jsid id)
|
||||
TypeSet::ObjectKey::property(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
|
@ -1113,7 +1113,7 @@ TypeSetObjectKey::property(jsid id)
|
|||
}
|
||||
|
||||
void
|
||||
TypeSetObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
|
||||
TypeSet::ObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
|
||||
{
|
||||
// If we are accessing a lazily defined property which actually exists in
|
||||
// the VM and has not been instantiated yet, instantiate it now if we are
|
||||
|
@ -1182,7 +1182,7 @@ class TypeConstraintFreezeStack : public TypeConstraint
|
|||
|
||||
const char *kind() { return "freezeStack"; }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
/*
|
||||
* Unlike TypeConstraintFreeze, triggering this constraint once does
|
||||
* not disable it on future changes to the type set.
|
||||
|
@ -1201,7 +1201,7 @@ class TypeConstraintFreezeStack : public TypeConstraint
|
|||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
types::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *constraints,
|
||||
js::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *constraints,
|
||||
RecompileInfo *precompileInfo)
|
||||
{
|
||||
if (constraints->failed())
|
||||
|
@ -1254,13 +1254,13 @@ types::FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintL
|
|||
break;
|
||||
}
|
||||
|
||||
if (!CheckFrozenTypeSet(cx, entry.thisTypes, types::TypeScript::ThisTypes(entry.script)))
|
||||
if (!CheckFrozenTypeSet(cx, entry.thisTypes, TypeScript::ThisTypes(entry.script)))
|
||||
succeeded = false;
|
||||
unsigned nargs = entry.script->functionNonDelazifying()
|
||||
? entry.script->functionNonDelazifying()->nargs()
|
||||
: 0;
|
||||
for (size_t i = 0; i < nargs; i++) {
|
||||
if (!CheckFrozenTypeSet(cx, &entry.argTypes[i], types::TypeScript::ArgTypes(entry.script, i)))
|
||||
if (!CheckFrozenTypeSet(cx, &entry.argTypes[i], TypeScript::ArgTypes(entry.script, i)))
|
||||
succeeded = false;
|
||||
}
|
||||
for (size_t i = 0; i < entry.script->nTypeSets(); i++) {
|
||||
|
@ -1310,7 +1310,7 @@ CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTyp
|
|||
}
|
||||
|
||||
void
|
||||
types::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
|
||||
js::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Assert no new types have been added to the StackTypeSets. Do this before
|
||||
|
@ -1364,7 +1364,7 @@ class ConstraintDataFreeze
|
|||
|
||||
const char *kind() { return "freeze"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return true; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return true; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return true; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) { return false; }
|
||||
|
||||
|
@ -1559,7 +1559,7 @@ class ConstraintDataFreezeObjectFlags
|
|||
|
||||
const char *kind() { return "freezeObjectFlags"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
return group->hasAnyFlags(flags);
|
||||
|
@ -1577,7 +1577,7 @@ class ConstraintDataFreezeObjectFlags
|
|||
} /* anonymous namespace */
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags)
|
||||
TypeSet::ObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags)
|
||||
{
|
||||
MOZ_ASSERT(flags);
|
||||
|
||||
|
@ -1595,7 +1595,7 @@ TypeSetObjectKey::hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags
|
|||
}
|
||||
|
||||
bool
|
||||
TypeSetObjectKey::hasStableClassAndProto(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::hasStableClassAndProto(CompilerConstraintList *constraints)
|
||||
{
|
||||
return !hasFlags(constraints, OBJECT_FLAG_UNKNOWN_PROPERTIES);
|
||||
}
|
||||
|
@ -1615,7 +1615,7 @@ TemporaryTypeSet::hasObjectFlags(CompilerConstraintList *constraints, ObjectGrou
|
|||
|
||||
unsigned count = getObjectCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key && key->hasFlags(constraints, flags))
|
||||
return true;
|
||||
}
|
||||
|
@ -1636,7 +1636,7 @@ ObjectGroup::initialHeap(CompilerConstraintList *constraints)
|
|||
if (!canPreTenure())
|
||||
return gc::DefaultHeap;
|
||||
|
||||
HeapTypeSetKey objectProperty = TypeSetObjectKey::get(this)->property(JSID_EMPTY);
|
||||
HeapTypeSetKey objectProperty = TypeSet::ObjectKey::get(this)->property(JSID_EMPTY);
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
|
||||
typedef CompilerConstraintInstance<ConstraintDataFreezeObjectFlags> T;
|
||||
|
@ -1659,7 +1659,7 @@ class ConstraintDataFreezeObjectForInlinedCall
|
|||
|
||||
const char *kind() { return "freezeObjectForInlinedCall"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
// We don't keep track of the exact dependencies the caller has on its
|
||||
|
@ -1691,7 +1691,7 @@ class ConstraintDataFreezeObjectForTypedArrayData
|
|||
|
||||
const char *kind() { return "freezeObjectForTypedArrayData"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) {
|
||||
TypedArrayObject &tarray = group->singleton()->as<TypedArrayObject>();
|
||||
|
@ -1713,7 +1713,7 @@ class ConstraintDataFreezeObjectForTypedArrayData
|
|||
} /* anonymous namespace */
|
||||
|
||||
void
|
||||
TypeSetObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constraints)
|
||||
{
|
||||
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
|
||||
LifoAlloc *alloc = constraints->alloc();
|
||||
|
@ -1723,7 +1723,7 @@ TypeSetObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constra
|
|||
}
|
||||
|
||||
void
|
||||
TypeSetObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints)
|
||||
TypeSet::ObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList *constraints)
|
||||
{
|
||||
TypedArrayObject &tarray = singleton()->as<TypedArrayObject>();
|
||||
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
|
||||
|
@ -1776,7 +1776,7 @@ class ConstraintDataFreezePropertyState
|
|||
|
||||
const char *kind() { return (which == NON_DATA) ? "freezeNonDataProperty" : "freezeNonWritableProperty"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) {
|
||||
return (which == NON_DATA)
|
||||
? property->nonDataProperty()
|
||||
|
@ -1832,7 +1832,7 @@ class ConstraintDataConstantProperty
|
|||
|
||||
const char *kind() { return "constantProperty"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) {
|
||||
return property->nonConstantProperty();
|
||||
}
|
||||
|
@ -1894,7 +1894,7 @@ class ConstraintDataInert
|
|||
|
||||
const char *kind() { return "inert"; }
|
||||
|
||||
bool invalidateOnNewType(Type type) { return false; }
|
||||
bool invalidateOnNewType(TypeSet::Type type) { return false; }
|
||||
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
|
||||
bool invalidateOnNewObjectState(ObjectGroup *group) { return false; }
|
||||
|
||||
|
@ -1937,7 +1937,7 @@ TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType)
|
|||
return unknown();
|
||||
|
||||
for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
|
||||
Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
|
||||
Type type = PrimitiveType(TypeFlagPrimitive(flag));
|
||||
if (type != filteredType && other->hasType(type) && !hasType(type))
|
||||
return false;
|
||||
}
|
||||
|
@ -1946,9 +1946,9 @@ TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType)
|
|||
return unknownObject();
|
||||
|
||||
for (size_t i = 0; i < other->getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = other->getObject(i);
|
||||
ObjectKey *key = other->getObject(i);
|
||||
if (key) {
|
||||
Type type = Type::ObjectType(key);
|
||||
Type type = ObjectType(key);
|
||||
if (type != filteredType && !hasType(type))
|
||||
return false;
|
||||
}
|
||||
|
@ -1968,7 +1968,7 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
|
|||
bool dontConvert = false;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
|
@ -1985,7 +1985,7 @@ TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
|
|||
// information incorrect), nor for non-array objects (as their elements
|
||||
// may point to emptyObjectElements, which cannot be converted).
|
||||
if (!property.maybeTypes() ||
|
||||
!property.maybeTypes()->hasType(Type::DoubleType()) ||
|
||||
!property.maybeTypes()->hasType(DoubleType()) ||
|
||||
key->clasp() != &ArrayObject::class_)
|
||||
{
|
||||
dontConvert = true;
|
||||
|
@ -2040,7 +2040,7 @@ TemporaryTypeSet::getKnownClass(CompilerConstraintList *constraints)
|
|||
|
||||
if (clasp) {
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key && !key->hasStableClassAndProto(constraints))
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2182,7 +2182,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints)
|
|||
unsigned count = getObjectCount();
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
|
@ -2202,7 +2202,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints)
|
|||
|
||||
// Guard against mutating __proto__.
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (key)
|
||||
JS_ALWAYS_TRUE(key->hasStableClassAndProto(constraints));
|
||||
}
|
||||
|
@ -2217,7 +2217,7 @@ TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList *constraints, jsid
|
|||
return true;
|
||||
|
||||
for (unsigned i = 0; i < getObjectCount(); i++) {
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
|
||||
|
@ -2241,11 +2241,11 @@ ClassCanHaveExtraProperties(const Class *clasp)
|
|||
|| IsAnyTypedArrayClass(clasp);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
PrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSObject *obj)
|
||||
{
|
||||
do {
|
||||
TypeSetObjectKey *key = TypeSetObjectKey::get(obj);
|
||||
TypeSet::ObjectKey *key = TypeSet::ObjectKey::get(obj);
|
||||
if (ClassCanHaveExtraProperties(key->clasp()))
|
||||
return true;
|
||||
if (key->unknownProperties())
|
||||
|
@ -2260,7 +2260,7 @@ PrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSObject *obj)
|
|||
}
|
||||
|
||||
bool
|
||||
types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSScript *script)
|
||||
js::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSScript *script)
|
||||
{
|
||||
if (JSObject *proto = script->global().maybeGetArrayPrototype())
|
||||
return PrototypeHasIndexedProperty(constraints, proto);
|
||||
|
@ -2268,7 +2268,7 @@ types::ArrayPrototypeHasIndexedProperty(CompilerConstraintList *constraints, JSS
|
|||
}
|
||||
|
||||
bool
|
||||
types::TypeCanHaveExtraIndexedProperties(CompilerConstraintList *constraints,
|
||||
js::TypeCanHaveExtraIndexedProperties(CompilerConstraintList *constraints,
|
||||
TemporaryTypeSet *types)
|
||||
{
|
||||
const Class *clasp = types->getKnownClass(constraints);
|
||||
|
@ -2348,7 +2348,7 @@ TypeZone::addPendingRecompile(JSContext *cx, JSScript *script)
|
|||
}
|
||||
|
||||
void
|
||||
types::PrintTypes(JSContext *cx, JSCompartment *comp, bool force)
|
||||
js::PrintTypes(JSContext *cx, JSCompartment *comp, bool force)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
gc::AutoSuppressGC suppressGC(cx);
|
||||
|
@ -2388,7 +2388,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
|||
|
||||
if (shape->hasGetterValue() || shape->hasSetterValue()) {
|
||||
types->setNonDataProperty(cx);
|
||||
types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc());
|
||||
types->TypeSet::addType(TypeSet::UnknownType(), &cx->typeLifoAlloc());
|
||||
} else if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
if (!indexed && types->canSetDefinite(shape->slot()))
|
||||
types->setDefinite(shape->slot());
|
||||
|
@ -2403,11 +2403,11 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
|||
* Also don't add untracked values (initial uninitialized lexical
|
||||
* magic values and optimized out values) as appearing in CallObjects.
|
||||
*/
|
||||
MOZ_ASSERT_IF(IsUntrackedValue(value), obj->is<CallObject>());
|
||||
MOZ_ASSERT_IF(TypeSet::IsUntrackedValue(value), obj->is<CallObject>());
|
||||
if ((indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) &&
|
||||
!IsUntrackedValue(value))
|
||||
!TypeSet::IsUntrackedValue(value))
|
||||
{
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
types->TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
|
||||
|
@ -2416,7 +2416,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
|
|||
} else {
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s - setConstant",
|
||||
InferSpewColor(types), types, InferSpewColorReset(),
|
||||
ObjectGroupString(obj->group()), TypeIdString(shape->propid()));
|
||||
TypeSet::ObjectGroupString(obj->group()), TypeIdString(shape->propid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2426,7 +2426,7 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *
|
|||
{
|
||||
InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
|
||||
InferSpewColor(types), types, InferSpewColorReset(),
|
||||
ObjectGroupString(this), TypeIdString(id));
|
||||
TypeSet::ObjectGroupString(this), TypeIdString(id));
|
||||
|
||||
if (!singleton() || !singleton()->isNative()) {
|
||||
types->setNonConstantProperty(cx);
|
||||
|
@ -2455,7 +2455,7 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *
|
|||
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
||||
const Value &value = obj->getDenseElement(i);
|
||||
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
Type type = GetValueType(value);
|
||||
TypeSet::Type type = TypeSet::GetValueType(value);
|
||||
types->TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
}
|
||||
|
@ -2531,7 +2531,7 @@ ObjectGroup::matchDefiniteProperties(HandleObject obj)
|
|||
}
|
||||
|
||||
void
|
||||
types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type type)
|
||||
js::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, TypeSet::Type type)
|
||||
{
|
||||
MOZ_ASSERT(id == IdToTypeId(id));
|
||||
|
||||
|
@ -2547,7 +2547,7 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
|||
// Clear any constant flag if it exists.
|
||||
if (!types->empty() && !types->nonConstantProperty()) {
|
||||
InferSpew(ISpewOps, "constantMutated: %sT%p%s %s",
|
||||
InferSpewColor(types), types, InferSpewColorReset(), TypeString(type));
|
||||
InferSpewColor(types), types, InferSpewColorReset(), TypeSet::TypeString(type));
|
||||
types->setNonConstantProperty(cx);
|
||||
}
|
||||
|
||||
|
@ -2555,7 +2555,7 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
|||
return;
|
||||
|
||||
InferSpew(ISpewOps, "externalType: property %s %s: %s",
|
||||
ObjectGroupString(group), TypeIdString(id), TypeString(type));
|
||||
TypeSet::ObjectGroupString(group), TypeIdString(id), TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
|
||||
// Propagate new types from partially initialized groups to fully
|
||||
|
@ -2565,15 +2565,15 @@ types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type
|
|||
// from acquiring the fully initialized group.
|
||||
if (group->newScript() && group->newScript()->initializedGroup()) {
|
||||
if (type.isObjectUnchecked() && types->unknownObject())
|
||||
type = Type::AnyObjectType();
|
||||
type = TypeSet::AnyObjectType();
|
||||
AddTypePropertyId(cx, group->newScript()->initializedGroup(), id, type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
types::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
js::AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value)
|
||||
{
|
||||
AddTypePropertyId(cx, group, id, GetValueType(value));
|
||||
AddTypePropertyId(cx, group, id, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2655,7 +2655,7 @@ ObjectGroup::setFlags(ExclusiveContext *cx, ObjectGroupFlags flags)
|
|||
|
||||
addFlags(flags);
|
||||
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", ObjectGroupString(this), flags);
|
||||
InferSpew(ISpewOps, "%s: setFlags 0x%x", TypeSet::ObjectGroupString(this), flags);
|
||||
|
||||
ObjectStateChange(cx, this, false);
|
||||
|
||||
|
@ -2673,7 +2673,7 @@ ObjectGroup::markUnknown(ExclusiveContext *cx)
|
|||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
InferSpew(ISpewOps, "UnknownProperties: %s", ObjectGroupString(this));
|
||||
InferSpew(ISpewOps, "UnknownProperties: %s", TypeSet::ObjectGroupString(this));
|
||||
|
||||
clearNewScript(cx);
|
||||
ObjectStateChange(cx, this, true);
|
||||
|
@ -2691,7 +2691,7 @@ ObjectGroup::markUnknown(ExclusiveContext *cx)
|
|||
for (unsigned i = 0; i < count; i++) {
|
||||
Property *prop = getProperty(i);
|
||||
if (prop) {
|
||||
prop->types.addType(cx, Type::UnknownType());
|
||||
prop->types.addType(cx, TypeSet::UnknownType());
|
||||
prop->types.setNonDataProperty(cx);
|
||||
}
|
||||
}
|
||||
|
@ -2800,8 +2800,8 @@ ObjectGroup::print()
|
|||
{
|
||||
TaggedProto tagged(proto());
|
||||
fprintf(stderr, "%s : %s",
|
||||
ObjectGroupString(this),
|
||||
tagged.isObject() ? TypeString(Type::ObjectType(tagged.toObject()))
|
||||
TypeSet::ObjectGroupString(this),
|
||||
tagged.isObject() ? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject()))
|
||||
: (tagged.isLazy() ? "(lazy)" : "(null)"));
|
||||
|
||||
if (unknownProperties()) {
|
||||
|
@ -2881,7 +2881,7 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
|
|||
group->clearNewScript(cx);
|
||||
}
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {}
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {}
|
||||
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (IsObjectGroupAboutToBeFinalized(&group))
|
||||
|
@ -2892,7 +2892,7 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
|
|||
};
|
||||
|
||||
bool
|
||||
types::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, ObjectGroup *group, HandleId id)
|
||||
js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, ObjectGroup *group, HandleId id)
|
||||
{
|
||||
/*
|
||||
* Ensure that if the properties named here could have a getter, setter or
|
||||
|
@ -2929,7 +2929,7 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint
|
|||
|
||||
const char *kind() { return "clearDefiniteSingle"; }
|
||||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {
|
||||
void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) {
|
||||
if (source->baseFlags() || source->getObjectCount() > 1)
|
||||
group->clearNewScript(cx);
|
||||
}
|
||||
|
@ -2943,7 +2943,7 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint
|
|||
};
|
||||
|
||||
bool
|
||||
types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
js::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
||||
JSScript *script, JSScript *calleeScript)
|
||||
{
|
||||
// Look for any uses of the specified calleeScript in type sets for
|
||||
|
@ -2954,7 +2954,8 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
|||
// contain a single object, as IonBuilder does not inline polymorphic sites
|
||||
// during the definite properties analysis.
|
||||
|
||||
TypeSetObjectKey *calleeKey = Type::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
|
||||
TypeSet::ObjectKey *calleeKey =
|
||||
TypeSet::ObjectType(calleeScript->functionNonDelazifying()).objectKey();
|
||||
|
||||
unsigned count = TypeScript::NumTypeSets(script);
|
||||
StackTypeSet *typeArray = script->types()->typeArray();
|
||||
|
@ -2990,8 +2991,7 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, ObjectGroup *group,
|
|||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args,
|
||||
bool constructing)
|
||||
js::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args, bool constructing)
|
||||
{
|
||||
unsigned nargs = callee->as<JSFunction>().nargs();
|
||||
JSScript *script = callee->as<JSFunction>().nonLazyScript();
|
||||
|
@ -3014,18 +3014,18 @@ types::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args
|
|||
}
|
||||
|
||||
static inline bool
|
||||
IsAboutToBeFinalized(TypeSetObjectKey **keyp)
|
||||
IsAboutToBeFinalized(TypeSet::ObjectKey **keyp)
|
||||
{
|
||||
// Mask out the low bit indicating whether this is a group or JS object.
|
||||
uintptr_t flagBit = uintptr_t(*keyp) & 1;
|
||||
gc::Cell *tmp = reinterpret_cast<gc::Cell *>(uintptr_t(*keyp) & ~1);
|
||||
bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp);
|
||||
*keyp = reinterpret_cast<TypeSetObjectKey *>(uintptr_t(tmp) | flagBit);
|
||||
*keyp = reinterpret_cast<TypeSet::ObjectKey *>(uintptr_t(tmp) | flagBit);
|
||||
return isAboutToBeFinalized;
|
||||
}
|
||||
|
||||
void
|
||||
types::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
||||
js::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
||||
{
|
||||
uint32_t added = 0;
|
||||
for (jsbytecode *pc = script->code(); pc < script->codeEnd(); pc += GetBytecodeLength(pc)) {
|
||||
|
@ -3040,7 +3040,7 @@ types::FillBytecodeTypeMap(JSScript *script, uint32_t *bytecodeMap)
|
|||
}
|
||||
|
||||
void
|
||||
types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
js::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const js::Value &rval)
|
||||
{
|
||||
/* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */
|
||||
if (!(js_CodeSpec[*pc].format & JOF_TYPESET))
|
||||
|
@ -3051,13 +3051,13 @@ types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const
|
|||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
Type type = GetValueType(rval);
|
||||
TypeSet::Type type = TypeSet::GetValueType(rval);
|
||||
StackTypeSet *types = TypeScript::BytecodeTypes(script, pc);
|
||||
if (types->hasType(type))
|
||||
return;
|
||||
|
||||
InferSpew(ISpewOps, "bytecodeType: %p %05u: %s",
|
||||
script, script->pcToOffset(pc), TypeString(type));
|
||||
script, script->pcToOffset(pc), TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
|
||||
|
@ -3688,18 +3688,18 @@ ConstraintTypeSet::sweep(Zone *zone, AutoClearTypeInferenceStateOnOOM &oom)
|
|||
*/
|
||||
unsigned objectCount = baseObjectCount();
|
||||
if (objectCount >= 2) {
|
||||
unsigned oldCapacity = HashSetCapacity(objectCount);
|
||||
TypeSetObjectKey **oldArray = objectSet;
|
||||
unsigned oldCapacity = TypeHashSet::Capacity(objectCount);
|
||||
ObjectKey **oldArray = objectSet;
|
||||
|
||||
clearObjects();
|
||||
objectCount = 0;
|
||||
for (unsigned i = 0; i < oldCapacity; i++) {
|
||||
TypeSetObjectKey *key = oldArray[i];
|
||||
ObjectKey *key = oldArray[i];
|
||||
if (!key)
|
||||
continue;
|
||||
if (!IsAboutToBeFinalized(&key)) {
|
||||
TypeSetObjectKey **pentry =
|
||||
HashSetInsert<TypeSetObjectKey *,TypeSetObjectKey,TypeSetObjectKey>
|
||||
ObjectKey **pentry =
|
||||
TypeHashSet::Insert<ObjectKey *, ObjectKey, ObjectKey>
|
||||
(zone->types.typeLifoAlloc, objectSet, objectCount, key);
|
||||
if (pentry) {
|
||||
*pentry = key;
|
||||
|
@ -3722,9 +3722,9 @@ ConstraintTypeSet::sweep(Zone *zone, AutoClearTypeInferenceStateOnOOM &oom)
|
|||
}
|
||||
setBaseObjectCount(objectCount);
|
||||
} else if (objectCount == 1) {
|
||||
TypeSetObjectKey *key = (TypeSetObjectKey *) objectSet;
|
||||
ObjectKey *key = (ObjectKey *) objectSet;
|
||||
if (!IsAboutToBeFinalized(&key)) {
|
||||
objectSet = reinterpret_cast<TypeSetObjectKey **>(key);
|
||||
objectSet = reinterpret_cast<ObjectKey **>(key);
|
||||
} else {
|
||||
// As above, mark type sets containing objects with unknown
|
||||
// properties as unknown.
|
||||
|
@ -3823,7 +3823,7 @@ ObjectGroup::maybeSweep(AutoClearTypeInferenceStateOnOOM *oom)
|
|||
*/
|
||||
unsigned propertyCount = basePropertyCount();
|
||||
if (propertyCount >= 2) {
|
||||
unsigned oldCapacity = HashSetCapacity(propertyCount);
|
||||
unsigned oldCapacity = TypeHashSet::Capacity(propertyCount);
|
||||
Property **oldArray = propertySet;
|
||||
|
||||
clearProperties();
|
||||
|
@ -3843,8 +3843,7 @@ ObjectGroup::maybeSweep(AutoClearTypeInferenceStateOnOOM *oom)
|
|||
|
||||
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
|
||||
if (newProp) {
|
||||
Property **pentry =
|
||||
HashSetInsert<jsid,Property,Property>
|
||||
Property **pentry = TypeHashSet::Insert<jsid, Property, Property>
|
||||
(typeLifoAlloc, propertySet, propertyCount, prop->id);
|
||||
if (pentry) {
|
||||
*pentry = newProp;
|
||||
|
|
570
js/src/jsinfer.h
570
js/src/jsinfer.h
|
@ -23,7 +23,6 @@
|
|||
#include "js/UbiNode.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/ObjectGroup.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -33,122 +32,12 @@ namespace jit {
|
|||
class TempAllocator;
|
||||
}
|
||||
|
||||
namespace types {
|
||||
|
||||
class TaggedProto;
|
||||
struct TypeZone;
|
||||
class TypeSet;
|
||||
struct TypeSetObjectKey;
|
||||
|
||||
/*
|
||||
* Information about a single concrete type. We pack this into a single word,
|
||||
* where small values are particular primitive or other singleton types, and
|
||||
* larger values are either specific JS objects or object groups.
|
||||
*/
|
||||
class Type
|
||||
{
|
||||
uintptr_t data;
|
||||
explicit Type(uintptr_t data) : data(data) {}
|
||||
|
||||
public:
|
||||
|
||||
uintptr_t raw() const { return data; }
|
||||
|
||||
bool isPrimitive() const {
|
||||
return data < JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isPrimitive(JSValueType type) const {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_OBJECT);
|
||||
return (uintptr_t) type == data;
|
||||
}
|
||||
|
||||
JSValueType primitive() const {
|
||||
MOZ_ASSERT(isPrimitive());
|
||||
return (JSValueType) data;
|
||||
}
|
||||
|
||||
bool isMagicArguments() const {
|
||||
return primitive() == JSVAL_TYPE_MAGIC;
|
||||
}
|
||||
|
||||
bool isSomeObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT || data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isAnyObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isUnknown() const {
|
||||
return data == JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Accessors for types that are either JSObject or ObjectGroup. */
|
||||
|
||||
bool isObject() const {
|
||||
MOZ_ASSERT(!isAnyObject() && !isUnknown());
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isObjectUnchecked() const {
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
inline TypeSetObjectKey *objectKey() const;
|
||||
|
||||
/* Accessors for JSObject types */
|
||||
|
||||
bool isSingleton() const {
|
||||
return isObject() && !!(data & 1);
|
||||
}
|
||||
|
||||
inline JSObject *singleton() const;
|
||||
inline JSObject *singletonNoBarrier() const;
|
||||
|
||||
/* Accessors for ObjectGroup types */
|
||||
|
||||
bool isGroup() const {
|
||||
return isObject() && !(data & 1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *group() const;
|
||||
inline ObjectGroup *groupNoBarrier() const;
|
||||
|
||||
bool operator == (Type o) const { return data == o.data; }
|
||||
bool operator != (Type o) const { return data != o.data; }
|
||||
|
||||
static inline Type UndefinedType() { return Type(JSVAL_TYPE_UNDEFINED); }
|
||||
static inline Type NullType() { return Type(JSVAL_TYPE_NULL); }
|
||||
static inline Type BooleanType() { return Type(JSVAL_TYPE_BOOLEAN); }
|
||||
static inline Type Int32Type() { return Type(JSVAL_TYPE_INT32); }
|
||||
static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); }
|
||||
static inline Type StringType() { return Type(JSVAL_TYPE_STRING); }
|
||||
static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); }
|
||||
static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); }
|
||||
static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); }
|
||||
static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); }
|
||||
|
||||
static inline Type PrimitiveType(JSValueType type) {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_UNKNOWN);
|
||||
return Type(type);
|
||||
}
|
||||
|
||||
static inline Type ObjectType(JSObject *obj);
|
||||
static inline Type ObjectType(ObjectGroup *group);
|
||||
static inline Type ObjectType(TypeSetObjectKey *key);
|
||||
|
||||
static js::ThingRootKind rootKind() { return js::THING_ROOT_TYPE; }
|
||||
};
|
||||
|
||||
/* Get the type of a jsval, or zero for an unknown special value. */
|
||||
inline Type GetValueType(const Value &val);
|
||||
|
||||
/*
|
||||
* Get the type of a possibly optimized out or uninitialized let value. This
|
||||
* generally only happens on unconditional type monitors on bailing out of
|
||||
* Ion, such as for argument and local types.
|
||||
*/
|
||||
inline Type GetMaybeUntrackedValueType(const Value &val);
|
||||
class TypeConstraint;
|
||||
class TypeNewScript;
|
||||
class CompilerConstraintList;
|
||||
class HeapTypeSetKey;
|
||||
|
||||
/*
|
||||
* Type inference memory management overview.
|
||||
|
@ -162,46 +51,6 @@ inline Type GetMaybeUntrackedValueType(const Value &val);
|
|||
* Thus, type set and constraints only hold weak references.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A constraint which listens to additions to a type set and propagates those
|
||||
* changes to other type sets.
|
||||
*/
|
||||
class TypeConstraint
|
||||
{
|
||||
public:
|
||||
/* Next constraint listening to the same type set. */
|
||||
TypeConstraint *next;
|
||||
|
||||
TypeConstraint()
|
||||
: next(nullptr)
|
||||
{}
|
||||
|
||||
/* Debugging name for this kind of constraint. */
|
||||
virtual const char *kind() = 0;
|
||||
|
||||
/* Register a new type for the set this constraint is listening to. */
|
||||
virtual void newType(JSContext *cx, TypeSet *source, Type type) = 0;
|
||||
|
||||
/*
|
||||
* For constraints attached to an object property's type set, mark the
|
||||
* property as having changed somehow.
|
||||
*/
|
||||
virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
|
||||
|
||||
/*
|
||||
* For constraints attached to the JSID_EMPTY type set on an object,
|
||||
* indicate a change in one of the object's dynamic property flags or other
|
||||
* state.
|
||||
*/
|
||||
virtual void newObjectState(JSContext *cx, ObjectGroup *group) {}
|
||||
|
||||
/*
|
||||
* If the data this constraint refers to is still live, copy it into the
|
||||
* zone's new allocator. Type constraints only hold weak references.
|
||||
*/
|
||||
virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0;
|
||||
};
|
||||
|
||||
/* Flags and other state stored in TypeSet::flags */
|
||||
enum : uint32_t {
|
||||
TYPE_FLAG_UNDEFINED = 0x1,
|
||||
|
@ -261,6 +110,81 @@ enum : uint32_t {
|
|||
};
|
||||
typedef uint32_t TypeFlags;
|
||||
|
||||
/* Flags and other state stored in ObjectGroup::Flags */
|
||||
enum : uint32_t {
|
||||
/* Whether this group is associated with some allocation site. */
|
||||
OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1,
|
||||
|
||||
/* (0x2 and 0x4 are unused) */
|
||||
|
||||
/* Mask/shift for the number of properties in propertySet */
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK = 0xfff8,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_SHIFT = 3,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_LIMIT =
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT,
|
||||
|
||||
/* Whether any objects this represents may have sparse indexes. */
|
||||
OBJECT_FLAG_SPARSE_INDEXES = 0x00010000,
|
||||
|
||||
/* Whether any objects this represents may not have packed dense elements. */
|
||||
OBJECT_FLAG_NON_PACKED = 0x00020000,
|
||||
|
||||
/*
|
||||
* Whether any objects this represents may be arrays whose length does not
|
||||
* fit in an int32.
|
||||
*/
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW = 0x00040000,
|
||||
|
||||
/* Whether any objects have been iterated over. */
|
||||
OBJECT_FLAG_ITERATED = 0x00080000,
|
||||
|
||||
/* For a global object, whether flags were set on the RegExpStatics. */
|
||||
OBJECT_FLAG_REGEXP_FLAGS_SET = 0x00100000,
|
||||
|
||||
/*
|
||||
* For the function on a run-once script, whether the function has actually
|
||||
* run multiple times.
|
||||
*/
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED = 0x00200000,
|
||||
|
||||
/*
|
||||
* For a global object, whether any array buffers in this compartment with
|
||||
* typed object views have been neutered.
|
||||
*/
|
||||
OBJECT_FLAG_TYPED_OBJECT_NEUTERED = 0x00400000,
|
||||
|
||||
/*
|
||||
* Whether objects with this type should be allocated directly in the
|
||||
* tenured heap.
|
||||
*/
|
||||
OBJECT_FLAG_PRE_TENURE = 0x00800000,
|
||||
|
||||
/* Whether objects with this type might have copy on write elements. */
|
||||
OBJECT_FLAG_COPY_ON_WRITE = 0x01000000,
|
||||
|
||||
/* Whether this type has had its 'new' script cleared in the past. */
|
||||
OBJECT_FLAG_NEW_SCRIPT_CLEARED = 0x02000000,
|
||||
|
||||
/*
|
||||
* Whether all properties of this object are considered unknown.
|
||||
* If set, all other flags in DYNAMIC_MASK will also be set.
|
||||
*/
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x04000000,
|
||||
|
||||
/* Flags which indicate dynamic properties of represented objects. */
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x07ff0000,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this group.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x38000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 27,
|
||||
|
||||
// Mask/shift for this group's generation. If out of sync with the
|
||||
// TypeZone's generation, this group hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x40000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 30,
|
||||
};
|
||||
typedef uint32_t ObjectGroupFlags;
|
||||
|
||||
class StackTypeSet;
|
||||
class HeapTypeSet;
|
||||
class TemporaryTypeSet;
|
||||
|
@ -271,11 +195,12 @@ class TemporaryTypeSet;
|
|||
*
|
||||
* - StackTypeSet are associated with TypeScripts, for arguments and values
|
||||
* observed at property reads. These are implicitly frozen on compilation
|
||||
* and do not have constraints attached to them.
|
||||
* and only have constraints added to them which can trigger invalidation of
|
||||
* TypeNewScript information.
|
||||
*
|
||||
* - HeapTypeSet are associated with the properties of ObjectGroups. These
|
||||
* may have constraints added to them to trigger invalidation of compiled
|
||||
* code.
|
||||
* may have constraints added to them to trigger invalidation of either
|
||||
* compiled code or TypeNewScript information.
|
||||
*
|
||||
* - TemporaryTypeSet are created during compilation and do not outlive
|
||||
* that compilation.
|
||||
|
@ -289,12 +214,162 @@ class TemporaryTypeSet;
|
|||
*/
|
||||
class TypeSet
|
||||
{
|
||||
public:
|
||||
// Type set entry for either a JSObject with singleton type or a
|
||||
// non-singleton ObjectGroup.
|
||||
class ObjectKey {
|
||||
public:
|
||||
static intptr_t keyBits(ObjectKey *obj) { return (intptr_t) obj; }
|
||||
static ObjectKey *getKey(ObjectKey *obj) { return obj; }
|
||||
|
||||
static inline ObjectKey *get(JSObject *obj);
|
||||
static inline ObjectKey *get(ObjectGroup *group);
|
||||
|
||||
bool isGroup() {
|
||||
return (uintptr_t(this) & 1) == 0;
|
||||
}
|
||||
bool isSingleton() {
|
||||
return (uintptr_t(this) & 1) != 0;
|
||||
}
|
||||
|
||||
inline ObjectGroup *group();
|
||||
inline JSObject *singleton();
|
||||
|
||||
inline ObjectGroup *groupNoBarrier();
|
||||
inline JSObject *singletonNoBarrier();
|
||||
|
||||
const Class *clasp();
|
||||
TaggedProto proto();
|
||||
TypeNewScript *newScript();
|
||||
|
||||
bool unknownProperties();
|
||||
bool hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags);
|
||||
bool hasStableClassAndProto(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext *cx, jsid id);
|
||||
|
||||
ObjectGroup *maybeGroup();
|
||||
};
|
||||
|
||||
// Information about a single concrete type. We pack this into one word,
|
||||
// where small values are particular primitive or other singleton types and
|
||||
// larger values are either specific JS objects or object groups.
|
||||
class Type
|
||||
{
|
||||
friend class TypeSet;
|
||||
|
||||
uintptr_t data;
|
||||
explicit Type(uintptr_t data) : data(data) {}
|
||||
|
||||
public:
|
||||
|
||||
uintptr_t raw() const { return data; }
|
||||
|
||||
bool isPrimitive() const {
|
||||
return data < JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isPrimitive(JSValueType type) const {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_OBJECT);
|
||||
return (uintptr_t) type == data;
|
||||
}
|
||||
|
||||
JSValueType primitive() const {
|
||||
MOZ_ASSERT(isPrimitive());
|
||||
return (JSValueType) data;
|
||||
}
|
||||
|
||||
bool isMagicArguments() const {
|
||||
return primitive() == JSVAL_TYPE_MAGIC;
|
||||
}
|
||||
|
||||
bool isSomeObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT || data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isAnyObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
bool isUnknown() const {
|
||||
return data == JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Accessors for types that are either JSObject or ObjectGroup. */
|
||||
|
||||
bool isObject() const {
|
||||
MOZ_ASSERT(!isAnyObject() && !isUnknown());
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isObjectUnchecked() const {
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
inline ObjectKey *objectKey() const;
|
||||
|
||||
/* Accessors for JSObject types */
|
||||
|
||||
bool isSingleton() const {
|
||||
return isObject() && !!(data & 1);
|
||||
}
|
||||
|
||||
inline JSObject *singleton() const;
|
||||
inline JSObject *singletonNoBarrier() const;
|
||||
|
||||
/* Accessors for ObjectGroup types */
|
||||
|
||||
bool isGroup() const {
|
||||
return isObject() && !(data & 1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *group() const;
|
||||
inline ObjectGroup *groupNoBarrier() const;
|
||||
|
||||
bool operator == (Type o) const { return data == o.data; }
|
||||
bool operator != (Type o) const { return data != o.data; }
|
||||
|
||||
static ThingRootKind rootKind() { return THING_ROOT_TYPE; }
|
||||
};
|
||||
|
||||
static inline Type UndefinedType() { return Type(JSVAL_TYPE_UNDEFINED); }
|
||||
static inline Type NullType() { return Type(JSVAL_TYPE_NULL); }
|
||||
static inline Type BooleanType() { return Type(JSVAL_TYPE_BOOLEAN); }
|
||||
static inline Type Int32Type() { return Type(JSVAL_TYPE_INT32); }
|
||||
static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); }
|
||||
static inline Type StringType() { return Type(JSVAL_TYPE_STRING); }
|
||||
static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); }
|
||||
static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); }
|
||||
static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); }
|
||||
static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); }
|
||||
|
||||
static inline Type PrimitiveType(JSValueType type) {
|
||||
MOZ_ASSERT(type < JSVAL_TYPE_UNKNOWN);
|
||||
return Type(type);
|
||||
}
|
||||
|
||||
static inline Type ObjectType(JSObject *obj);
|
||||
static inline Type ObjectType(ObjectGroup *group);
|
||||
static inline Type ObjectType(ObjectKey *key);
|
||||
|
||||
static const char *NonObjectTypeString(Type type);
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *TypeString(Type type);
|
||||
static const char *ObjectGroupString(ObjectGroup *group);
|
||||
#else
|
||||
static const char *TypeString(Type type) { return nullptr; }
|
||||
static const char *ObjectGroupString(ObjectGroup *group) { return nullptr; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/* Flags for this type set. */
|
||||
TypeFlags flags;
|
||||
|
||||
/* Possible objects this type set can represent. */
|
||||
TypeSetObjectKey **objectSet;
|
||||
ObjectKey **objectSet;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -350,7 +425,7 @@ class TypeSet
|
|||
* may return nullptr.
|
||||
*/
|
||||
inline unsigned getObjectCount() const;
|
||||
inline TypeSetObjectKey *getObject(unsigned i) const;
|
||||
inline ObjectKey *getObject(unsigned i) const;
|
||||
inline JSObject *getSingleton(unsigned i) const;
|
||||
inline ObjectGroup *getGroup(unsigned i) const;
|
||||
inline JSObject *getSingletonNoBarrier(unsigned i) const;
|
||||
|
@ -412,6 +487,58 @@ class TypeSet
|
|||
inline void setBaseObjectCount(uint32_t count);
|
||||
|
||||
void clearObjects();
|
||||
|
||||
public:
|
||||
static inline Type GetValueType(const Value &val);
|
||||
|
||||
static inline bool IsUntrackedValue(const Value &val);
|
||||
|
||||
// Get the type of a possibly optimized out or uninitialized let value.
|
||||
// This generally only happens on unconditional type monitors on bailing
|
||||
// out of Ion, such as for argument and local types.
|
||||
static inline Type GetMaybeUntrackedValueType(const Value &val);
|
||||
|
||||
static void MarkTypeRoot(JSTracer *trc, Type *v, const char *name);
|
||||
};
|
||||
|
||||
/*
|
||||
* A constraint which listens to additions to a type set and propagates those
|
||||
* changes to other type sets.
|
||||
*/
|
||||
class TypeConstraint
|
||||
{
|
||||
public:
|
||||
/* Next constraint listening to the same type set. */
|
||||
TypeConstraint *next;
|
||||
|
||||
TypeConstraint()
|
||||
: next(nullptr)
|
||||
{}
|
||||
|
||||
/* Debugging name for this kind of constraint. */
|
||||
virtual const char *kind() = 0;
|
||||
|
||||
/* Register a new type for the set this constraint is listening to. */
|
||||
virtual void newType(JSContext *cx, TypeSet *source, TypeSet::Type type) = 0;
|
||||
|
||||
/*
|
||||
* For constraints attached to an object property's type set, mark the
|
||||
* property as having changed somehow.
|
||||
*/
|
||||
virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
|
||||
|
||||
/*
|
||||
* For constraints attached to the JSID_EMPTY type set on an object,
|
||||
* indicate a change in one of the object's dynamic property flags or other
|
||||
* state.
|
||||
*/
|
||||
virtual void newObjectState(JSContext *cx, ObjectGroup *group) {}
|
||||
|
||||
/*
|
||||
* If the data this constraint refers to is still live, copy it into the
|
||||
* zone's new allocator. Type constraints only hold weak references.
|
||||
*/
|
||||
virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0;
|
||||
};
|
||||
|
||||
// If there is an OOM while sweeping types, the type information is deoptimized
|
||||
|
@ -487,7 +614,7 @@ class TemporaryTypeSet : public TypeSet
|
|||
TemporaryTypeSet() {}
|
||||
TemporaryTypeSet(LifoAlloc *alloc, Type type);
|
||||
|
||||
TemporaryTypeSet(uint32_t flags, TypeSetObjectKey **objectSet) {
|
||||
TemporaryTypeSet(uint32_t flags, ObjectKey **objectSet) {
|
||||
this->flags = flags;
|
||||
this->objectSet = objectSet;
|
||||
}
|
||||
|
@ -772,66 +899,6 @@ class TypeNewScript
|
|||
/* Is this a reasonable PC to be doing inlining on? */
|
||||
inline bool isInlinableCall(jsbytecode *pc);
|
||||
|
||||
/*
|
||||
* Type information about a property.
|
||||
*
|
||||
* The type sets in the properties of a group describe the possible values
|
||||
* that can be read out of that property in actual JS objects. In native
|
||||
* objects, property types account for plain data properties (those with a
|
||||
* slot and no getter or setter hook) and dense elements. In typed objects
|
||||
* and unboxed objects, property types account for object and value
|
||||
* properties and elements in the object.
|
||||
*
|
||||
* For accesses on these properties, the correspondence is as follows:
|
||||
*
|
||||
* 1. If the group has unknownProperties(), the possible properties and
|
||||
* value types for associated JSObjects are unknown.
|
||||
*
|
||||
* 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
|
||||
* in |obj|, before obj->getProperty(id) the property in |group| for
|
||||
* |id| must reflect the result of the getProperty.
|
||||
*
|
||||
* There are several exceptions to this:
|
||||
*
|
||||
* 1. For properties of global JS objects which are undefined at the point
|
||||
* where the property was (lazily) generated, the property type set will
|
||||
* remain empty, and the 'undefined' type will only be added after a
|
||||
* subsequent assignment or deletion. After these properties have been
|
||||
* assigned a defined value, the only way they can become undefined
|
||||
* again is after such an assign or deletion.
|
||||
*
|
||||
* 2. Array lengths are special cased by the compiler and VM and are not
|
||||
* reflected in property types.
|
||||
*
|
||||
* 3. In typed objects (but not unboxed objects), the initial values of
|
||||
* properties (null pointers and undefined values) are not reflected in
|
||||
* the property types. These values are always possible when reading the
|
||||
* property.
|
||||
*
|
||||
* We establish these by using write barriers on calls to setProperty and
|
||||
* defineProperty which are on native properties, and on any jitcode which
|
||||
* might update the property with a new type.
|
||||
*/
|
||||
struct Property
|
||||
{
|
||||
/* Identifier for this property, JSID_VOID for the aggregate integer index property. */
|
||||
HeapId id;
|
||||
|
||||
/* Possible types for this property, including types inherited from prototypes. */
|
||||
HeapTypeSet types;
|
||||
|
||||
explicit Property(jsid id)
|
||||
: id(id)
|
||||
{}
|
||||
|
||||
Property(const Property &o)
|
||||
: id(o.id.get()), types(o.types)
|
||||
{}
|
||||
|
||||
static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
|
||||
static jsid getKey(Property *p) { return p->id; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Whether Array.prototype, or an object on its proto chain, has an
|
||||
* indexed property.
|
||||
|
@ -894,9 +961,10 @@ class TypeScript
|
|||
static inline void MonitorAssign(JSContext *cx, HandleObject obj, jsid id);
|
||||
|
||||
/* Add a type for a variable in a script. */
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, Type type);
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, TypeSet::Type type);
|
||||
static inline void SetThis(JSContext *cx, JSScript *script, const js::Value &value);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg,
|
||||
TypeSet::Type type);
|
||||
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg,
|
||||
const js::Value &value);
|
||||
|
||||
|
@ -940,45 +1008,6 @@ FinishCompilation(JSContext *cx, HandleScript script, CompilerConstraintList *co
|
|||
void
|
||||
FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints);
|
||||
|
||||
class HeapTypeSetKey;
|
||||
|
||||
// Type set entry for either a JSObject with singleton type or a non-singleton ObjectGroup.
|
||||
struct TypeSetObjectKey
|
||||
{
|
||||
static intptr_t keyBits(TypeSetObjectKey *obj) { return (intptr_t) obj; }
|
||||
static TypeSetObjectKey *getKey(TypeSetObjectKey *obj) { return obj; }
|
||||
|
||||
static inline TypeSetObjectKey *get(JSObject *obj);
|
||||
static inline TypeSetObjectKey *get(ObjectGroup *group);
|
||||
|
||||
bool isGroup() {
|
||||
return (uintptr_t(this) & 1) == 0;
|
||||
}
|
||||
bool isSingleton() {
|
||||
return (uintptr_t(this) & 1) != 0;
|
||||
}
|
||||
|
||||
inline ObjectGroup *group();
|
||||
inline JSObject *singleton();
|
||||
|
||||
inline ObjectGroup *groupNoBarrier();
|
||||
inline JSObject *singletonNoBarrier();
|
||||
|
||||
const Class *clasp();
|
||||
TaggedProto proto();
|
||||
TypeNewScript *newScript();
|
||||
|
||||
bool unknownProperties();
|
||||
bool hasFlags(CompilerConstraintList *constraints, ObjectGroupFlags flags);
|
||||
bool hasStableClassAndProto(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext *cx, jsid id);
|
||||
|
||||
ObjectGroup *maybeGroup();
|
||||
};
|
||||
|
||||
// Representation of a heap type property which may or may not be instantiated.
|
||||
// Heap properties for singleton types are instantiated lazily as they are used
|
||||
// by the compiler, but this is only done on the main thread. If we are
|
||||
|
@ -989,10 +1018,10 @@ struct TypeSetObjectKey
|
|||
// during generation of baseline caches.
|
||||
class HeapTypeSetKey
|
||||
{
|
||||
friend struct TypeSetObjectKey;
|
||||
friend class TypeSet::ObjectKey;
|
||||
|
||||
// Object and property being accessed.
|
||||
TypeSetObjectKey *object_;
|
||||
TypeSet::ObjectKey *object_;
|
||||
jsid id_;
|
||||
|
||||
// If instantiated, the underlying heap type set.
|
||||
|
@ -1003,7 +1032,7 @@ class HeapTypeSetKey
|
|||
: object_(nullptr), id_(JSID_EMPTY), maybeTypes_(nullptr)
|
||||
{}
|
||||
|
||||
TypeSetObjectKey *object() const { return object_; }
|
||||
TypeSet::ObjectKey *object() const { return object_; }
|
||||
jsid id() const { return id_; }
|
||||
HeapTypeSet *maybeTypes() const { return maybeTypes_; }
|
||||
|
||||
|
@ -1166,8 +1195,6 @@ enum SpewChannel {
|
|||
SPEW_COUNT
|
||||
};
|
||||
|
||||
const char *NonObjectTypeString(Type type);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
const char * InferSpewColorReset();
|
||||
|
@ -1175,11 +1202,9 @@ const char * InferSpewColor(TypeConstraint *constraint);
|
|||
const char * InferSpewColor(TypeSet *types);
|
||||
|
||||
void InferSpew(SpewChannel which, const char *fmt, ...);
|
||||
const char * TypeString(Type type);
|
||||
const char * ObjectGroupString(ObjectGroup *group);
|
||||
|
||||
/* Check that the type property for id in group contains value. */
|
||||
bool TypeHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
bool ObjectGroupHasProperty(JSContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -1187,8 +1212,6 @@ inline const char * InferSpewColorReset() { return nullptr; }
|
|||
inline const char * InferSpewColor(TypeConstraint *constraint) { return nullptr; }
|
||||
inline const char * InferSpewColor(TypeSet *types) { return nullptr; }
|
||||
inline void InferSpew(SpewChannel which, const char *fmt, ...) {}
|
||||
inline const char * TypeString(Type type) { return nullptr; }
|
||||
inline const char * ObjectGroupString(ObjectGroup *group) { return nullptr; }
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1199,7 +1222,6 @@ MOZ_NORETURN MOZ_COLD void TypeFailure(JSContext *cx, const char *fmt, ...);
|
|||
void
|
||||
PrintTypes(JSContext *cx, JSCompartment *comp, bool force);
|
||||
|
||||
} /* namespace types */
|
||||
} /* namespace js */
|
||||
|
||||
// JS::ubi::Nodes can point to object groups; they're js::gc::Cell instances
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "jscntxtinlines.h"
|
||||
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// CompilerOutput & RecompileInfo
|
||||
|
@ -92,40 +91,40 @@ RecompileInfo::shouldSweep(TypeZone &types)
|
|||
// Types
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* static */ inline TypeSetObjectKey *
|
||||
TypeSetObjectKey::get(JSObject *obj)
|
||||
/* static */ inline TypeSet::ObjectKey *
|
||||
TypeSet::ObjectKey::get(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(obj);
|
||||
if (obj->isSingleton())
|
||||
return (TypeSetObjectKey *) (uintptr_t(obj) | 1);
|
||||
return (TypeSetObjectKey *) obj->group();
|
||||
return (ObjectKey *) (uintptr_t(obj) | 1);
|
||||
return (ObjectKey *) obj->group();
|
||||
}
|
||||
|
||||
/* static */ inline TypeSetObjectKey *
|
||||
TypeSetObjectKey::get(ObjectGroup *group)
|
||||
/* static */ inline TypeSet::ObjectKey *
|
||||
TypeSet::ObjectKey::get(ObjectGroup *group)
|
||||
{
|
||||
MOZ_ASSERT(group);
|
||||
if (group->singleton())
|
||||
return (TypeSetObjectKey *) (uintptr_t(group->singleton()) | 1);
|
||||
return (TypeSetObjectKey *) group;
|
||||
return (ObjectKey *) (uintptr_t(group->singleton()) | 1);
|
||||
return (ObjectKey *) group;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSetObjectKey::groupNoBarrier()
|
||||
TypeSet::ObjectKey::groupNoBarrier()
|
||||
{
|
||||
MOZ_ASSERT(isGroup());
|
||||
return (ObjectGroup *) this;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSetObjectKey::singletonNoBarrier()
|
||||
TypeSet::ObjectKey::singletonNoBarrier()
|
||||
{
|
||||
MOZ_ASSERT(isSingleton());
|
||||
return (JSObject *) (uintptr_t(this) & ~1);
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSetObjectKey::group()
|
||||
TypeSet::ObjectKey::group()
|
||||
{
|
||||
ObjectGroup *res = groupNoBarrier();
|
||||
ObjectGroup::readBarrier(res);
|
||||
|
@ -133,56 +132,56 @@ TypeSetObjectKey::group()
|
|||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSetObjectKey::singleton()
|
||||
TypeSet::ObjectKey::singleton()
|
||||
{
|
||||
JSObject *res = singletonNoBarrier();
|
||||
JSObject::readBarrier(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(JSObject *obj)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(JSObject *obj)
|
||||
{
|
||||
if (obj->isSingleton())
|
||||
return Type(uintptr_t(obj) | 1);
|
||||
return Type(uintptr_t(obj->group()));
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(ObjectGroup *group)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectGroup *group)
|
||||
{
|
||||
if (group->singleton())
|
||||
return Type(uintptr_t(group->singleton()) | 1);
|
||||
return Type(uintptr_t(group));
|
||||
}
|
||||
|
||||
/* static */ inline Type
|
||||
Type::ObjectType(TypeSetObjectKey *obj)
|
||||
/* static */ inline TypeSet::Type
|
||||
TypeSet::ObjectType(ObjectKey *obj)
|
||||
{
|
||||
return Type(uintptr_t(obj));
|
||||
}
|
||||
|
||||
inline Type
|
||||
GetValueType(const Value &val)
|
||||
inline TypeSet::Type
|
||||
TypeSet::GetValueType(const Value &val)
|
||||
{
|
||||
if (val.isDouble())
|
||||
return Type::DoubleType();
|
||||
return TypeSet::DoubleType();
|
||||
if (val.isObject())
|
||||
return Type::ObjectType(&val.toObject());
|
||||
return Type::PrimitiveType(val.extractNonDoubleType());
|
||||
return TypeSet::ObjectType(&val.toObject());
|
||||
return TypeSet::PrimitiveType(val.extractNonDoubleType());
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsUntrackedValue(const Value &val)
|
||||
TypeSet::IsUntrackedValue(const Value &val)
|
||||
{
|
||||
return val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
|
||||
val.whyMagic() == JS_UNINITIALIZED_LEXICAL);
|
||||
}
|
||||
|
||||
inline Type
|
||||
GetMaybeUntrackedValueType(const Value &val)
|
||||
inline TypeSet::Type
|
||||
TypeSet::GetMaybeUntrackedValueType(const Value &val)
|
||||
{
|
||||
return IsUntrackedValue(val) ? Type::UnknownType() : GetValueType(val);
|
||||
return IsUntrackedValue(val) ? UnknownType() : GetValueType(val);
|
||||
}
|
||||
|
||||
inline TypeFlags
|
||||
|
@ -398,7 +397,7 @@ PropertyHasBeenMarkedNonConstant(JSObject *obj, jsid id)
|
|||
}
|
||||
|
||||
inline bool
|
||||
HasTypePropertyId(JSObject *obj, jsid id, Type type)
|
||||
HasTypePropertyId(JSObject *obj, jsid id, TypeSet::Type type)
|
||||
{
|
||||
if (obj->hasLazyGroup())
|
||||
return true;
|
||||
|
@ -415,15 +414,15 @@ HasTypePropertyId(JSObject *obj, jsid id, Type type)
|
|||
inline bool
|
||||
HasTypePropertyId(JSObject *obj, jsid id, const Value &value)
|
||||
{
|
||||
return HasTypePropertyId(obj, id, GetValueType(value));
|
||||
return HasTypePropertyId(obj, id, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, Type type);
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, TypeSet::Type type);
|
||||
void AddTypePropertyId(ExclusiveContext *cx, ObjectGroup *group, jsid id, const Value &value);
|
||||
|
||||
/* Add a possible type for a property of obj. */
|
||||
inline void
|
||||
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, Type type)
|
||||
AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, TypeSet::Type type)
|
||||
{
|
||||
id = IdToTypeId(id);
|
||||
if (TrackPropertyTypes(cx, obj, id))
|
||||
|
@ -489,10 +488,8 @@ MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
/* Interface helpers for JSScript*. */
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
const js::Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
js::types::Type type);
|
||||
extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const Value &rval);
|
||||
extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet::Type type);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Script interface functions
|
||||
|
@ -622,7 +619,7 @@ TypeScript::MonitorAssign(JSContext *cx, HandleObject obj, jsid id)
|
|||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, TypeSet::Type type)
|
||||
{
|
||||
StackTypeSet *types = ThisTypes(script);
|
||||
if (!types)
|
||||
|
@ -632,7 +629,7 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
|||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setThis %p: %s",
|
||||
script, TypeString(type));
|
||||
script, TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
}
|
||||
|
@ -640,11 +637,11 @@ TypeScript::SetThis(JSContext *cx, JSScript *script, Type type)
|
|||
/* static */ inline void
|
||||
TypeScript::SetThis(JSContext *cx, JSScript *script, const js::Value &value)
|
||||
{
|
||||
SetThis(cx, script, GetValueType(value));
|
||||
SetThis(cx, script, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type)
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, TypeSet::Type type)
|
||||
{
|
||||
StackTypeSet *types = ArgTypes(script, arg);
|
||||
if (!types)
|
||||
|
@ -654,7 +651,7 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
|
|||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
InferSpew(ISpewOps, "externalType: setArg %p %u: %s",
|
||||
script, arg, TypeString(type));
|
||||
script, arg, TypeSet::TypeString(type));
|
||||
types->addType(cx, type);
|
||||
}
|
||||
}
|
||||
|
@ -662,29 +659,29 @@ TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type
|
|||
/* static */ inline void
|
||||
TypeScript::SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value)
|
||||
{
|
||||
Type type = GetValueType(value);
|
||||
SetArgument(cx, script, arg, type);
|
||||
SetArgument(cx, script, arg, TypeSet::GetValueType(value));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeSet
|
||||
// TypeHashSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* The sets of objects and scripts in a type set grow monotonically, are usually
|
||||
* empty, almost always small, and sometimes big. For empty or singleton sets,
|
||||
* the pointer refers directly to the value. For sets fitting into SET_ARRAY_SIZE,
|
||||
* an array of this length is used to store the elements. For larger sets, a hash
|
||||
* table filled to 25%-50% of capacity is used, with collisions resolved by linear
|
||||
* probing. TODO: replace these with jshashtables.
|
||||
*/
|
||||
const unsigned SET_ARRAY_SIZE = 8;
|
||||
const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
|
||||
|
||||
/* Get the capacity of a set with the given element count. */
|
||||
static inline unsigned
|
||||
HashSetCapacity(unsigned count)
|
||||
// Hashing code shared by objects in TypeSets and properties in ObjectGroups.
|
||||
struct TypeHashSet
|
||||
{
|
||||
// The sets of objects in a type set grow monotonically, are usually empty,
|
||||
// almost always small, and sometimes big. For empty or singleton sets, the
|
||||
// the pointer refers directly to the value. For sets fitting into
|
||||
// SET_ARRAY_SIZE, an array of this length is used to store the elements.
|
||||
// For larger sets, a hash table filled to 25%-50% of capacity is used,
|
||||
// with collisions resolved by linear probing.
|
||||
static const unsigned SET_ARRAY_SIZE = 8;
|
||||
static const unsigned SET_CAPACITY_OVERFLOW = 1u << 30;
|
||||
|
||||
// Get the capacity of a set with the given element count.
|
||||
static inline unsigned
|
||||
Capacity(unsigned count)
|
||||
{
|
||||
MOZ_ASSERT(count >= 2);
|
||||
MOZ_ASSERT(count < SET_CAPACITY_OVERFLOW);
|
||||
|
||||
|
@ -692,33 +689,31 @@ HashSetCapacity(unsigned count)
|
|||
return SET_ARRAY_SIZE;
|
||||
|
||||
return 1u << (mozilla::FloorLog2(count) + 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the FNV hash for the low 32 bits of v. */
|
||||
template <class T, class KEY>
|
||||
static inline uint32_t
|
||||
HashKey(T v)
|
||||
{
|
||||
// Compute the FNV hash for the low 32 bits of v.
|
||||
template <class T, class KEY>
|
||||
static inline uint32_t
|
||||
HashKey(T v)
|
||||
{
|
||||
uint32_t nv = KEY::keyBits(v);
|
||||
|
||||
uint32_t hash = 84696351 ^ (nv & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 8) & 0xff);
|
||||
hash = (hash * 16777619) ^ ((nv >> 16) & 0xff);
|
||||
return (hash * 16777619) ^ ((nv >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert space for an element into the specified set and grow its capacity if needed.
|
||||
* returned value is an existing or new entry (nullptr if new).
|
||||
*/
|
||||
template <class T, class U, class KEY>
|
||||
static U **
|
||||
HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
unsigned capacity = HashSetCapacity(count);
|
||||
// Insert space for an element into the specified set and grow its capacity
|
||||
// if needed. returned value is an existing or new entry (nullptr if new).
|
||||
template <class T, class U, class KEY>
|
||||
static U **
|
||||
InsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
unsigned capacity = Capacity(count);
|
||||
unsigned insertpos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
/* Whether we are converting from a fixed array to hashtable. */
|
||||
// Whether we are converting from a fixed array to hashtable.
|
||||
bool converting = (count == SET_ARRAY_SIZE);
|
||||
|
||||
if (!converting) {
|
||||
|
@ -733,7 +728,7 @@ HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
|||
return nullptr;
|
||||
|
||||
count++;
|
||||
unsigned newCapacity = HashSetCapacity(count);
|
||||
unsigned newCapacity = Capacity(count);
|
||||
|
||||
if (newCapacity == capacity) {
|
||||
MOZ_ASSERT(!converting);
|
||||
|
@ -760,16 +755,14 @@ HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
|||
while (values[insertpos] != nullptr)
|
||||
insertpos = (insertpos + 1) & (newCapacity - 1);
|
||||
return &values[insertpos];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert an element into the specified set if it is not already there, returning
|
||||
* an entry which is nullptr if the element was not there.
|
||||
*/
|
||||
template <class T, class U, class KEY>
|
||||
static inline U **
|
||||
HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
// Insert an element into the specified set if it is not already there,
|
||||
// returning an entry which is nullptr if the element was not there.
|
||||
template <class T, class U, class KEY>
|
||||
static inline U **
|
||||
Insert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
||||
{
|
||||
if (count == 0) {
|
||||
MOZ_ASSERT(values == nullptr);
|
||||
count++;
|
||||
|
@ -805,14 +798,14 @@ HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
|
|||
}
|
||||
}
|
||||
|
||||
return HashSetInsertTry<T,U,KEY>(alloc, values, count, key);
|
||||
}
|
||||
return InsertTry<T,U,KEY>(alloc, values, count, key);
|
||||
}
|
||||
|
||||
/* Lookup an entry in a hash set, return nullptr if it does not exist. */
|
||||
template <class T, class U, class KEY>
|
||||
static inline U *
|
||||
HashSetLookup(U **values, unsigned count, T key)
|
||||
{
|
||||
// Lookup an entry in a hash set, return nullptr if it does not exist.
|
||||
template <class T, class U, class KEY>
|
||||
static inline U *
|
||||
Lookup(U **values, unsigned count, T key)
|
||||
{
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
|
||||
|
@ -827,7 +820,7 @@ HashSetLookup(U **values, unsigned count, T key)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned capacity = HashSetCapacity(count);
|
||||
unsigned capacity = Capacity(count);
|
||||
unsigned pos = HashKey<T,KEY>(key) & (capacity - 1);
|
||||
|
||||
while (values[pos] != nullptr) {
|
||||
|
@ -837,35 +830,40 @@ HashSetLookup(U **values, unsigned count, T key)
|
|||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline TypeSetObjectKey *
|
||||
Type::objectKey() const
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// TypeSet
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline TypeSet::ObjectKey *
|
||||
TypeSet::Type::objectKey() const
|
||||
{
|
||||
MOZ_ASSERT(isObject());
|
||||
return (TypeSetObjectKey *) data;
|
||||
return (ObjectKey *) data;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
Type::singleton() const
|
||||
TypeSet::Type::singleton() const
|
||||
{
|
||||
return objectKey()->singleton();
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
Type::group() const
|
||||
TypeSet::Type::group() const
|
||||
{
|
||||
return objectKey()->group();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
Type::singletonNoBarrier() const
|
||||
TypeSet::Type::singletonNoBarrier() const
|
||||
{
|
||||
return objectKey()->singletonNoBarrier();
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
Type::groupNoBarrier() const
|
||||
TypeSet::Type::groupNoBarrier() const
|
||||
{
|
||||
return objectKey()->groupNoBarrier();
|
||||
}
|
||||
|
@ -884,7 +882,7 @@ TypeSet::hasType(Type type) const
|
|||
return !!(flags & TYPE_FLAG_ANYOBJECT);
|
||||
} else {
|
||||
return !!(flags & TYPE_FLAG_ANYOBJECT) ||
|
||||
HashSetLookup<TypeSetObjectKey*,TypeSetObjectKey,TypeSetObjectKey>
|
||||
TypeHashSet::Lookup<ObjectKey*, ObjectKey, ObjectKey>
|
||||
(objectSet, baseObjectCount(), type.objectKey()) != nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -947,18 +945,18 @@ TypeSet::getObjectCount() const
|
|||
{
|
||||
MOZ_ASSERT(!unknownObject());
|
||||
uint32_t count = baseObjectCount();
|
||||
if (count > SET_ARRAY_SIZE)
|
||||
return HashSetCapacity(count);
|
||||
if (count > TypeHashSet::SET_ARRAY_SIZE)
|
||||
return TypeHashSet::Capacity(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
inline TypeSetObjectKey *
|
||||
inline TypeSet::ObjectKey *
|
||||
TypeSet::getObject(unsigned i) const
|
||||
{
|
||||
MOZ_ASSERT(i < getObjectCount());
|
||||
if (baseObjectCount() == 1) {
|
||||
MOZ_ASSERT(i == 0);
|
||||
return (TypeSetObjectKey *) objectSet;
|
||||
return (ObjectKey *) objectSet;
|
||||
}
|
||||
return objectSet[i];
|
||||
}
|
||||
|
@ -966,28 +964,28 @@ TypeSet::getObject(unsigned i) const
|
|||
inline JSObject *
|
||||
TypeSet::getSingleton(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isSingleton()) ? key->singleton() : nullptr;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSet::getGroup(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isGroup()) ? key->group() : nullptr;
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
TypeSet::getSingletonNoBarrier(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isSingleton()) ? key->singletonNoBarrier() : nullptr;
|
||||
}
|
||||
|
||||
inline ObjectGroup *
|
||||
TypeSet::getGroupNoBarrier(unsigned i) const
|
||||
{
|
||||
TypeSetObjectKey *key = getObject(i);
|
||||
ObjectKey *key = getObject(i);
|
||||
return (key && key->isGroup()) ? key->groupNoBarrier() : nullptr;
|
||||
}
|
||||
|
||||
|
@ -1016,8 +1014,6 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
|
|||
newScript->trace(zone->barrierTracer());
|
||||
}
|
||||
|
||||
} // namespace types
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// ObjectGroup
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -1037,24 +1033,24 @@ ObjectGroup::setBasePropertyCount(uint32_t count)
|
|||
| (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
|
||||
}
|
||||
|
||||
inline types::HeapTypeSet *
|
||||
inline HeapTypeSet *
|
||||
ObjectGroup::getProperty(ExclusiveContext *cx, jsid id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == types::IdToTypeId(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
if (types::HeapTypeSet *types = maybeGetProperty(id))
|
||||
if (HeapTypeSet *types = maybeGetProperty(id))
|
||||
return types;
|
||||
|
||||
types::Property *base = cx->typeLifoAlloc().new_<types::Property>(id);
|
||||
Property *base = cx->typeLifoAlloc().new_<Property>(id);
|
||||
if (!base) {
|
||||
markUnknown(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t propertyCount = basePropertyCount();
|
||||
types::Property **pprop = types::HashSetInsert<jsid,types::Property,types::Property>
|
||||
Property **pprop = TypeHashSet::Insert<jsid, Property, Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
markUnknown(cx);
|
||||
|
@ -1078,14 +1074,14 @@ ObjectGroup::getProperty(ExclusiveContext *cx, jsid id)
|
|||
return &base->types;
|
||||
}
|
||||
|
||||
inline types::HeapTypeSet *
|
||||
inline HeapTypeSet *
|
||||
ObjectGroup::maybeGetProperty(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == types::IdToTypeId(id));
|
||||
MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
|
||||
MOZ_ASSERT(!unknownProperties());
|
||||
|
||||
types::Property *prop = types::HashSetLookup<jsid,types::Property,types::Property>
|
||||
Property *prop = TypeHashSet::Lookup<jsid, Property, Property>
|
||||
(propertySet, basePropertyCount(), id);
|
||||
|
||||
return prop ? &prop->types : nullptr;
|
||||
|
@ -1095,37 +1091,37 @@ inline unsigned
|
|||
ObjectGroup::getPropertyCount()
|
||||
{
|
||||
uint32_t count = basePropertyCount();
|
||||
if (count > types::SET_ARRAY_SIZE)
|
||||
return types::HashSetCapacity(count);
|
||||
if (count > TypeHashSet::SET_ARRAY_SIZE)
|
||||
return TypeHashSet::Capacity(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
inline types::Property *
|
||||
inline ObjectGroup::Property *
|
||||
ObjectGroup::getProperty(unsigned i)
|
||||
{
|
||||
MOZ_ASSERT(i < getPropertyCount());
|
||||
if (basePropertyCount() == 1) {
|
||||
MOZ_ASSERT(i == 0);
|
||||
return (types::Property *) propertySet;
|
||||
return (Property *) propertySet;
|
||||
}
|
||||
return propertySet[i];
|
||||
}
|
||||
|
||||
template <>
|
||||
struct GCMethods<const types::Type>
|
||||
struct GCMethods<const TypeSet::Type>
|
||||
{
|
||||
static types::Type initial() { return types::Type::UnknownType(); }
|
||||
static bool poisoned(const types::Type &v) {
|
||||
static TypeSet::Type initial() { return TypeSet::UnknownType(); }
|
||||
static bool poisoned(TypeSet::Type v) {
|
||||
return (v.isGroup() && IsPoisonedPtr(v.group()))
|
||||
|| (v.isSingleton() && IsPoisonedPtr(v.singleton()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GCMethods<types::Type>
|
||||
struct GCMethods<TypeSet::Type>
|
||||
{
|
||||
static types::Type initial() { return types::Type::UnknownType(); }
|
||||
static bool poisoned(const types::Type &v) {
|
||||
static TypeSet::Type initial() { return TypeSet::UnknownType(); }
|
||||
static bool poisoned(TypeSet::Type v) {
|
||||
return (v.isGroup() && IsPoisonedPtr(v.group()))
|
||||
|| (v.isSingleton() && IsPoisonedPtr(v.singleton()));
|
||||
}
|
||||
|
@ -1133,7 +1129,7 @@ struct GCMethods<types::Type>
|
|||
|
||||
} // namespace js
|
||||
|
||||
inline js::types::TypeScript *
|
||||
inline js::TypeScript *
|
||||
JSScript::types()
|
||||
{
|
||||
maybeSweepTypes(nullptr);
|
||||
|
|
|
@ -580,7 +580,7 @@ VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVecto
|
|||
|
||||
if (obj->isSingleton() && !obj->setIteratedSingleton(cx))
|
||||
return false;
|
||||
types::MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
|
||||
Rooted<PropertyIteratorObject *> iterobj(cx, NewPropertyIteratorObject(cx, flags));
|
||||
if (!iterobj)
|
||||
|
@ -623,7 +623,7 @@ VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVec
|
|||
|
||||
if (obj->isSingleton() && !obj->setIteratedSingleton(cx))
|
||||
return false;
|
||||
types::MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_ITERATED);
|
||||
|
||||
Rooted<PropertyIteratorObject*> iterobj(cx, NewPropertyIteratorObject(cx, flags));
|
||||
if (!iterobj)
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "vm/String-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::Abs;
|
||||
using mozilla::ArrayLength;
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
|
@ -1605,7 +1604,7 @@ CreateThisForFunctionWithGroup(JSContext *cx, HandleObjectGroup group, JSObject
|
|||
if (group->maybeUnboxedLayout() && newKind != SingletonObject)
|
||||
return UnboxedPlainObject::create(cx, group, newKind);
|
||||
|
||||
if (types::TypeNewScript *newScript = group->newScript()) {
|
||||
if (TypeNewScript *newScript = group->newScript()) {
|
||||
if (newScript->analyzed()) {
|
||||
// The definite properties analysis has been performed for this
|
||||
// group, so get the shape and finalize kind to use from the
|
||||
|
@ -1685,7 +1684,7 @@ js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject
|
|||
JSScript *script = callee->as<JSFunction>().getOrCreateScript(cx);
|
||||
if (!script)
|
||||
return nullptr;
|
||||
TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
|
||||
TypeScript::SetThis(cx, script, TypeSet::ObjectType(res));
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -1711,7 +1710,7 @@ js::CreateThisForFunction(JSContext *cx, HandleObject callee, NewObjectKind newK
|
|||
NativeObject::clear(cx, nobj);
|
||||
|
||||
JSScript *calleeScript = callee->as<JSFunction>().nonLazyScript();
|
||||
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
|
||||
TypeScript::SetThis(cx, calleeScript, TypeSet::ObjectType(nobj));
|
||||
|
||||
return nobj;
|
||||
}
|
||||
|
@ -3335,7 +3334,7 @@ js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::Hand
|
|||
if (!NativeObject::sparsifyDenseElements(cx, obj.as<NativeObject>()))
|
||||
return false;
|
||||
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
}
|
||||
|
||||
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
|
||||
|
|
|
@ -177,7 +177,7 @@ js::GetElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t in
|
|||
inline bool
|
||||
js::DeleteProperty(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
|
||||
{
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
if (DeletePropertyOp op = obj->getOps()->deleteProperty)
|
||||
return op(cx, obj, id, succeeded);
|
||||
return NativeDeleteProperty(cx, obj.as<NativeObject>(), id, succeeded);
|
||||
|
@ -198,7 +198,7 @@ js::DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeed
|
|||
inline bool
|
||||
js::SetPropertyAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
|
||||
{
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
SetAttributesOp op = obj->getOps()->setAttributes;
|
||||
if (op)
|
||||
return op(cx, obj, id, attrsp);
|
||||
|
@ -758,7 +758,7 @@ NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
|
|||
{
|
||||
// Use AutoEnterAnalysis to prohibit both any GC activity under the
|
||||
// callback, and any reentering of JS via Invoke() etc.
|
||||
types::AutoEnterAnalysis enter(cx);
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
if (!cx->compartment()->callObjectMetadataCallback(cx, pmetadata))
|
||||
return false;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsFinite;
|
||||
using mozilla::Maybe;
|
||||
|
|
|
@ -823,7 +823,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
|
||||
private:
|
||||
/* Persistent type information retained across GCs. */
|
||||
js::types::TypeScript *types_;
|
||||
js::TypeScript *types_;
|
||||
|
||||
// This script's ScriptSourceObject, or a CCW thereof.
|
||||
//
|
||||
|
@ -1455,9 +1455,9 @@ class JSScript : public js::gc::TenuredCell
|
|||
/* Ensure the script has a TypeScript. */
|
||||
inline bool ensureHasTypes(JSContext *cx);
|
||||
|
||||
inline js::types::TypeScript *types();
|
||||
inline js::TypeScript *types();
|
||||
|
||||
void maybeSweepTypes(js::types::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
void maybeSweepTypes(js::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
|
||||
inline js::GlobalObject &global() const;
|
||||
js::GlobalObject &uninlinedGlobal() const;
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
using namespace js::unicode;
|
||||
|
||||
using JS::Symbol;
|
||||
|
@ -3788,7 +3787,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedObjectGroup group(cx, ObjectGroup::callingAllocationSiteGroup(cx, JSProto_Array));
|
||||
if (!group)
|
||||
return false;
|
||||
AddTypePropertyId(cx, group, JSID_VOID, Type::StringType());
|
||||
AddTypePropertyId(cx, group, JSID_VOID, TypeSet::StringType());
|
||||
|
||||
/* Step 5: Use the second argument as the split limit, if given. */
|
||||
uint32_t limit;
|
||||
|
|
|
@ -340,7 +340,7 @@ ArgSetter(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHand
|
|||
if (arg < argsobj->initialLength() && !argsobj->isElementDeleted(arg)) {
|
||||
argsobj->setElement(cx, arg, vp);
|
||||
if (arg < script->functionNonDelazifying()->nargs())
|
||||
types::TypeScript::SetArgument(cx, script, arg, vp);
|
||||
TypeScript::SetArgument(cx, script, arg, vp);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -58,7 +58,6 @@ using mozilla::UniquePtr;
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
/*
|
||||
* Convert |v| to an array index for an array of length |length| per
|
||||
|
@ -523,7 +522,7 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer,
|
|||
// flag change will be observed.
|
||||
if (!cx->global()->getGroup(cx))
|
||||
CrashAtUnhandlableOOM("ArrayBufferObject::neuter");
|
||||
types::MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
|
||||
MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_NEUTERED);
|
||||
cx->compartment()->neuteredTypedObjects = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ ArrayObject::setLength(ExclusiveContext *cx, uint32_t length)
|
|||
|
||||
if (length > INT32_MAX) {
|
||||
/* Track objects with overflowing lengths in type information. */
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_LENGTH_OVERFLOW);
|
||||
}
|
||||
|
||||
getElementsHeader()->length = length;
|
||||
|
|
|
@ -1910,7 +1910,7 @@ UpdateExecutionObservabilityOfScriptsInZone(JSContext *cx, Zone *zone,
|
|||
// Iterate through observable scripts, invalidating their Ion scripts and
|
||||
// appending them to a vector for discarding their baseline scripts later.
|
||||
{
|
||||
types::AutoEnterAnalysis enter(fop, zone);
|
||||
AutoEnterAnalysis enter(fop, zone);
|
||||
if (JSScript *script = obs.singleScriptForZoneInvalidation()) {
|
||||
if (obs.shouldRecompileOrInvalidate(script)) {
|
||||
if (!AppendAndInvalidateScript(cx, zone, script, scripts))
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
JSObject *
|
||||
GeneratorObject::create(JSContext *cx, AbstractFramePtr frame)
|
||||
|
|
|
@ -199,7 +199,7 @@ GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JS
|
|||
if (clasp->spec.shouldDefineConstructor()) {
|
||||
// Stash type information, so that what we do here is equivalent to
|
||||
// initBuiltinConstructor.
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -224,7 +224,7 @@ GlobalObject::initBuiltinConstructor(JSContext *cx, Handle<GlobalObject*> global
|
|||
global->setPrototype(key, ObjectValue(*proto));
|
||||
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
|
||||
|
||||
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::NumberEqualsInt32;
|
||||
|
@ -1322,7 +1321,7 @@ static MOZ_ALWAYS_INLINE bool
|
|||
SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, const Value &value,
|
||||
bool strict, JSScript *script = nullptr, jsbytecode *pc = nullptr)
|
||||
{
|
||||
types::TypeScript::MonitorAssign(cx, obj, id);
|
||||
TypeScript::MonitorAssign(cx, obj, id);
|
||||
|
||||
if (obj->isNative() && JSID_IS_INT(id)) {
|
||||
uint32_t length = obj->as<NativeObject>().getDenseInitializedLength();
|
||||
|
@ -3963,8 +3962,7 @@ js::RunOnceScriptPrologue(JSContext *cx, HandleScript script)
|
|||
if (!script->functionNonDelazifying()->getGroup(cx))
|
||||
return false;
|
||||
|
||||
types::MarkObjectGroupFlags(cx, script->functionNonDelazifying(),
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED);
|
||||
MarkObjectGroupFlags(cx, script->functionNonDelazifying(), OBJECT_FLAG_RUNONCE_INVALIDATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,9 +81,9 @@ NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index,
|
|||
{
|
||||
// Avoid a slow AddTypePropertyId call if the type is the same as the type
|
||||
// of the previous element.
|
||||
types::Type thisType = types::GetValueType(val);
|
||||
if (index == 0 || types::GetValueType(elements_[index - 1]) != thisType)
|
||||
types::AddTypePropertyId(cx, this, JSID_VOID, thisType);
|
||||
TypeSet::Type thisType = TypeSet::GetValueType(val);
|
||||
if (index == 0 || TypeSet::GetValueType(elements_[index - 1]) != thisType)
|
||||
AddTypePropertyId(cx, this, JSID_VOID, thisType);
|
||||
setDenseElementMaybeConvertDouble(index, val);
|
||||
}
|
||||
|
||||
|
@ -92,14 +92,14 @@ NativeObject::initDenseElementWithType(ExclusiveContext *cx, uint32_t index,
|
|||
const Value &val)
|
||||
{
|
||||
MOZ_ASSERT(!shouldConvertDoubleElements());
|
||||
types::AddTypePropertyId(cx, this, JSID_VOID, val);
|
||||
AddTypePropertyId(cx, this, JSID_VOID, val);
|
||||
initDenseElement(index, val);
|
||||
}
|
||||
|
||||
inline void
|
||||
NativeObject::setDenseElementHole(ExclusiveContext *cx, uint32_t index)
|
||||
{
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
setDenseElement(index, MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,7 @@ NativeObject::setDenseElementHole(ExclusiveContext *cx, uint32_t index)
|
|||
NativeObject::removeDenseElementForSparseIndex(ExclusiveContext *cx,
|
||||
HandleNativeObject obj, uint32_t index)
|
||||
{
|
||||
types::MarkObjectGroupFlags(cx, obj,
|
||||
OBJECT_FLAG_NON_PACKED |
|
||||
OBJECT_FLAG_SPARSE_INDEXES);
|
||||
MarkObjectGroupFlags(cx, obj, OBJECT_FLAG_NON_PACKED | OBJECT_FLAG_SPARSE_INDEXES);
|
||||
if (obj->containsDenseElement(index))
|
||||
obj->setDenseElement(index, MagicValue(JS_ELEMENTS_HOLE));
|
||||
}
|
||||
|
@ -124,7 +122,7 @@ inline void
|
|||
NativeObject::markDenseElementsNotPacked(ExclusiveContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(isNative());
|
||||
types::MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
MarkObjectGroupFlags(cx, this, OBJECT_FLAG_NON_PACKED);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -320,7 +318,7 @@ NativeObject::setSlotWithType(ExclusiveContext *cx, Shape *shape,
|
|||
if (overwriting)
|
||||
shape->setOverwritten();
|
||||
|
||||
types::AddTypePropertyId(cx, this, shape->propid(), value);
|
||||
AddTypePropertyId(cx, this, shape->propid(), value);
|
||||
}
|
||||
|
||||
/* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
|
||||
|
|
|
@ -1118,15 +1118,15 @@ UpdateShapeTypeAndValue(ExclusiveContext *cx, NativeObject *obj, Shape *shape, c
|
|||
// Per the acquired properties analysis, when the shape of a partially
|
||||
// initialized object is changed to its fully initialized shape, its
|
||||
// group can be updated as well.
|
||||
if (types::TypeNewScript *newScript = obj->groupRaw()->newScript()) {
|
||||
if (TypeNewScript *newScript = obj->groupRaw()->newScript()) {
|
||||
if (newScript->initializedShape() == shape)
|
||||
obj->setGroup(newScript->initializedGroup());
|
||||
}
|
||||
}
|
||||
if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter())
|
||||
types::MarkTypePropertyNonData(cx, obj, id);
|
||||
MarkTypePropertyNonData(cx, obj, id);
|
||||
if (!shape->writable())
|
||||
types::MarkTypePropertyNonWritable(cx, obj, id);
|
||||
MarkTypePropertyNonWritable(cx, obj, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1596,7 +1596,7 @@ GetExistingProperty(JSContext *cx,
|
|||
!obj->isSingleton() &&
|
||||
!obj->template is<ScopeObject>() &&
|
||||
shape->hasDefaultGetter(),
|
||||
js::types::TypeHasProperty(cx, obj->group(), shape->propid(), vp));
|
||||
ObjectGroupHasProperty(cx, obj->group(), shape->propid(), vp));
|
||||
} else {
|
||||
vp.setUndefined();
|
||||
}
|
||||
|
@ -2294,7 +2294,7 @@ js::NativeSetPropertyAttributes(JSContext *cx, HandleNativeObject obj, HandleId
|
|||
if (!NativeObject::changePropertyAttributes(cx, nobj.as<NativeObject>(), shape, *attrsp))
|
||||
return false;
|
||||
if (*attrsp & JSPROP_READONLY)
|
||||
types::MarkTypePropertyNonWritable(cx, nobj, id);
|
||||
MarkTypePropertyNonWritable(cx, nobj, id);
|
||||
return true;
|
||||
} else {
|
||||
return SetPropertyAttributes(cx, nobj, id, attrsp);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::PodZero;
|
||||
|
||||
|
@ -549,22 +548,22 @@ ObjectGroup::defaultNewGroup(ExclusiveContext *cx, const Class *clasp,
|
|||
const JSAtomState &names = cx->names();
|
||||
|
||||
if (obj->is<RegExpObject>()) {
|
||||
AddTypePropertyId(cx, group, NameToId(names.source), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.global), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.ignoreCase), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.multiline), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.sticky), Type::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lastIndex), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.source), TypeSet::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.global), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.ignoreCase), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.multiline), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.sticky), TypeSet::BooleanType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lastIndex), TypeSet::Int32Type());
|
||||
}
|
||||
|
||||
if (obj->is<StringObject>())
|
||||
AddTypePropertyId(cx, group, NameToId(names.length), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.length), TypeSet::Int32Type());
|
||||
|
||||
if (obj->is<ErrorObject>()) {
|
||||
AddTypePropertyId(cx, group, NameToId(names.fileName), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lineNumber), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.columnNumber), Type::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.stack), Type::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.fileName), TypeSet::StringType());
|
||||
AddTypePropertyId(cx, group, NameToId(names.lineNumber), TypeSet::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.columnNumber), TypeSet::Int32Type());
|
||||
AddTypePropertyId(cx, group, NameToId(names.stack), TypeSet::StringType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -715,14 +714,14 @@ ObjectGroup::defaultNewGroup(JSContext *cx, JSProtoKey key)
|
|||
|
||||
struct ObjectGroupCompartment::ArrayObjectKey : public DefaultHasher<ArrayObjectKey>
|
||||
{
|
||||
Type type;
|
||||
TypeSet::Type type;
|
||||
JSObject *proto;
|
||||
|
||||
ArrayObjectKey()
|
||||
: type(Type::UndefinedType()), proto(nullptr)
|
||||
: type(TypeSet::UndefinedType()), proto(nullptr)
|
||||
{}
|
||||
|
||||
ArrayObjectKey(Type type, JSObject *proto)
|
||||
ArrayObjectKey(TypeSet::Type type, JSObject *proto)
|
||||
: type(type), proto(proto)
|
||||
{}
|
||||
|
||||
|
@ -744,7 +743,7 @@ struct ObjectGroupCompartment::ArrayObjectKey : public DefaultHasher<ArrayObject
|
|||
};
|
||||
|
||||
static inline bool
|
||||
NumberTypes(Type a, Type b)
|
||||
NumberTypes(TypeSet::Type a, TypeSet::Type b)
|
||||
{
|
||||
return (a.isPrimitive(JSVAL_TYPE_INT32) || a.isPrimitive(JSVAL_TYPE_DOUBLE))
|
||||
&& (b.isPrimitive(JSVAL_TYPE_INT32) || b.isPrimitive(JSVAL_TYPE_DOUBLE));
|
||||
|
@ -755,10 +754,10 @@ NumberTypes(Type a, Type b)
|
|||
* their default prototype. These are the only values that should appear in
|
||||
* arrays and objects whose type can be fixed.
|
||||
*/
|
||||
static inline Type
|
||||
static inline TypeSet::Type
|
||||
GetValueTypeForTable(const Value &v)
|
||||
{
|
||||
Type type = GetValueType(v);
|
||||
TypeSet::Type type = TypeSet::GetValueType(v);
|
||||
MOZ_ASSERT(!type.isSingleton());
|
||||
return type;
|
||||
}
|
||||
|
@ -779,13 +778,13 @@ ObjectGroup::fixArrayGroup(ExclusiveContext *cx, ArrayObject *obj)
|
|||
if (len == 0)
|
||||
return;
|
||||
|
||||
Type type = GetValueTypeForTable(obj->getDenseElement(0));
|
||||
TypeSet::Type type = GetValueTypeForTable(obj->getDenseElement(0));
|
||||
|
||||
for (unsigned i = 1; i < len; i++) {
|
||||
Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
|
||||
TypeSet::Type ntype = GetValueTypeForTable(obj->getDenseElement(i));
|
||||
if (ntype != type) {
|
||||
if (NumberTypes(type, ntype))
|
||||
type = Type::DoubleType();
|
||||
type = TypeSet::DoubleType();
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
@ -801,11 +800,12 @@ ObjectGroup::fixRestArgumentsGroup(ExclusiveContext *cx, ArrayObject *obj)
|
|||
|
||||
// Tracking element types for rest argument arrays is not worth it, but we
|
||||
// still want it to be known that it's a dense array.
|
||||
setGroupToHomogenousArray(cx, obj, Type::UnknownType());
|
||||
setGroupToHomogenousArray(cx, obj, TypeSet::UnknownType());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ObjectGroup::setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj, Type elementType)
|
||||
ObjectGroup::setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj,
|
||||
TypeSet::Type elementType)
|
||||
{
|
||||
MOZ_ASSERT(cx->zone()->types.activeAnalysis);
|
||||
|
||||
|
@ -888,7 +888,7 @@ struct ObjectGroupCompartment::PlainObjectEntry
|
|||
{
|
||||
ReadBarrieredObjectGroup group;
|
||||
ReadBarrieredShape shape;
|
||||
Type *types;
|
||||
TypeSet::Type *types;
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
|
@ -898,8 +898,8 @@ ObjectGroupCompartment::updatePlainObjectEntryTypes(ExclusiveContext *cx, PlainO
|
|||
if (entry.group->unknownProperties())
|
||||
return;
|
||||
for (size_t i = 0; i < nproperties; i++) {
|
||||
Type type = entry.types[i];
|
||||
Type ntype = GetValueTypeForTable(properties[i].value);
|
||||
TypeSet::Type type = entry.types[i];
|
||||
TypeSet::Type ntype = GetValueTypeForTable(properties[i].value);
|
||||
if (ntype == type)
|
||||
continue;
|
||||
if (ntype.isPrimitive(JSVAL_TYPE_INT32) &&
|
||||
|
@ -911,7 +911,7 @@ ObjectGroupCompartment::updatePlainObjectEntryTypes(ExclusiveContext *cx, PlainO
|
|||
type.isPrimitive(JSVAL_TYPE_INT32))
|
||||
{
|
||||
/* Include 'double' in the property types to avoid the update below later. */
|
||||
entry.types[i] = Type::DoubleType();
|
||||
entry.types[i] = TypeSet::DoubleType();
|
||||
}
|
||||
AddTypePropertyId(cx, entry.group, IdToTypeId(properties[i].id), ntype);
|
||||
}
|
||||
|
@ -986,7 +986,8 @@ ObjectGroup::fixPlainObjectGroup(ExclusiveContext *cx, PlainObject *obj)
|
|||
if (!ids)
|
||||
return;
|
||||
|
||||
ScopedJSFreePtr<Type> types(group->zone()->pod_calloc<Type>(properties.length()));
|
||||
ScopedJSFreePtr<TypeSet::Type> types(
|
||||
group->zone()->pod_calloc<TypeSet::Type>(properties.length()));
|
||||
if (!types)
|
||||
return;
|
||||
|
||||
|
@ -1240,16 +1241,12 @@ ObjectGroup::getCopyOnWriteObject(JSScript *script, jsbytecode *pc)
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
ObjectGroup::findAllocationSiteForType(JSContext *cx, Type type,
|
||||
ObjectGroup::findAllocationSite(JSContext *cx, ObjectGroup *group,
|
||||
JSScript **script, uint32_t *offset)
|
||||
{
|
||||
*script = nullptr;
|
||||
*offset = 0;
|
||||
|
||||
if (type.isUnknown() || type.isAnyObject() || !type.isGroup())
|
||||
return false;
|
||||
ObjectGroup *obj = type.group();
|
||||
|
||||
const ObjectGroupCompartment::AllocationSiteTable *table =
|
||||
cx->compartment()->objectGroups.allocationSiteTable;
|
||||
|
||||
|
@ -1260,7 +1257,7 @@ ObjectGroup::findAllocationSiteForType(JSContext *cx, Type type,
|
|||
!r.empty();
|
||||
r.popFront())
|
||||
{
|
||||
if (obj == r.front().value()) {
|
||||
if (group == r.front().value()) {
|
||||
*script = r.front().key().script;
|
||||
*offset = r.front().key().offset;
|
||||
return true;
|
||||
|
@ -1395,7 +1392,7 @@ ObjectGroupCompartment::sweep(FreeOp *fop)
|
|||
if (IsObjectGroupAboutToBeFinalizedFromAnyThread(&group))
|
||||
remove = true;
|
||||
else
|
||||
key.type = Type::ObjectType(group);
|
||||
key.type = TypeSet::ObjectType(group);
|
||||
}
|
||||
if (key.proto && key.proto != TaggedProto::LazyProto &&
|
||||
IsObjectAboutToBeFinalizedFromAnyThread(&key.proto))
|
||||
|
@ -1441,7 +1438,7 @@ ObjectGroupCompartment::sweep(FreeOp *fop)
|
|||
if (IsObjectGroupAboutToBeFinalizedFromAnyThread(&group))
|
||||
remove = true;
|
||||
else if (group != entry.types[i].groupNoBarrier())
|
||||
entry.types[i] = Type::ObjectType(group);
|
||||
entry.types[i] = TypeSet::ObjectType(group);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "jsbytecode.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsinfer.h"
|
||||
|
||||
#include "ds/IdValuePair.h"
|
||||
#include "gc/Barrier.h"
|
||||
|
@ -18,17 +19,11 @@ namespace js {
|
|||
class TypeDescr;
|
||||
class UnboxedLayout;
|
||||
|
||||
namespace types {
|
||||
|
||||
class Type;
|
||||
class TypeNewScript;
|
||||
class HeapTypeSet;
|
||||
struct Property;
|
||||
class AutoClearTypeInferenceStateOnOOM;
|
||||
class CompilerConstraintList;
|
||||
|
||||
} // namespace types
|
||||
|
||||
// Information about an object prototype, which can be either a particular
|
||||
// object, null, or a lazily generated object. The latter is only used by
|
||||
// certain kinds of proxies.
|
||||
|
@ -118,81 +113,6 @@ class RootedBase<TaggedProto> : public TaggedProtoOperations<Rooted<TaggedProto>
|
|||
}
|
||||
};
|
||||
|
||||
/* Flags and other state stored in ObjectGroupFlags */
|
||||
enum : uint32_t {
|
||||
/* Whether this group is associated with some allocation site. */
|
||||
OBJECT_FLAG_FROM_ALLOCATION_SITE = 0x1,
|
||||
|
||||
/* (0x2 and 0x4 are unused) */
|
||||
|
||||
/* Mask/shift for the number of properties in propertySet */
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK = 0xfff8,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_SHIFT = 3,
|
||||
OBJECT_FLAG_PROPERTY_COUNT_LIMIT =
|
||||
OBJECT_FLAG_PROPERTY_COUNT_MASK >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT,
|
||||
|
||||
/* Whether any objects this represents may have sparse indexes. */
|
||||
OBJECT_FLAG_SPARSE_INDEXES = 0x00010000,
|
||||
|
||||
/* Whether any objects this represents may not have packed dense elements. */
|
||||
OBJECT_FLAG_NON_PACKED = 0x00020000,
|
||||
|
||||
/*
|
||||
* Whether any objects this represents may be arrays whose length does not
|
||||
* fit in an int32.
|
||||
*/
|
||||
OBJECT_FLAG_LENGTH_OVERFLOW = 0x00040000,
|
||||
|
||||
/* Whether any objects have been iterated over. */
|
||||
OBJECT_FLAG_ITERATED = 0x00080000,
|
||||
|
||||
/* For a global object, whether flags were set on the RegExpStatics. */
|
||||
OBJECT_FLAG_REGEXP_FLAGS_SET = 0x00100000,
|
||||
|
||||
/*
|
||||
* For the function on a run-once script, whether the function has actually
|
||||
* run multiple times.
|
||||
*/
|
||||
OBJECT_FLAG_RUNONCE_INVALIDATED = 0x00200000,
|
||||
|
||||
/*
|
||||
* For a global object, whether any array buffers in this compartment with
|
||||
* typed object views have been neutered.
|
||||
*/
|
||||
OBJECT_FLAG_TYPED_OBJECT_NEUTERED = 0x00400000,
|
||||
|
||||
/*
|
||||
* Whether objects with this type should be allocated directly in the
|
||||
* tenured heap.
|
||||
*/
|
||||
OBJECT_FLAG_PRE_TENURE = 0x00800000,
|
||||
|
||||
/* Whether objects with this type might have copy on write elements. */
|
||||
OBJECT_FLAG_COPY_ON_WRITE = 0x01000000,
|
||||
|
||||
/* Whether this type has had its 'new' script cleared in the past. */
|
||||
OBJECT_FLAG_NEW_SCRIPT_CLEARED = 0x02000000,
|
||||
|
||||
/*
|
||||
* Whether all properties of this object are considered unknown.
|
||||
* If set, all other flags in DYNAMIC_MASK will also be set.
|
||||
*/
|
||||
OBJECT_FLAG_UNKNOWN_PROPERTIES = 0x04000000,
|
||||
|
||||
/* Flags which indicate dynamic properties of represented objects. */
|
||||
OBJECT_FLAG_DYNAMIC_MASK = 0x07ff0000,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this group.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x38000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 27,
|
||||
|
||||
// Mask/shift for this group's generation. If out of sync with the
|
||||
// TypeZone's generation, this group hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x40000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 30,
|
||||
};
|
||||
typedef uint32_t ObjectGroupFlags;
|
||||
|
||||
/*
|
||||
* Lazy object groups overview.
|
||||
*
|
||||
|
@ -301,9 +221,9 @@ class ObjectGroup : public gc::TenuredCell
|
|||
((flags_ & OBJECT_FLAG_ADDENDUM_MASK) >> OBJECT_FLAG_ADDENDUM_SHIFT);
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScriptDontCheckGeneration() const {
|
||||
TypeNewScript *newScriptDontCheckGeneration() const {
|
||||
if (addendumKind() == Addendum_NewScript)
|
||||
return reinterpret_cast<types::TypeNewScript *>(addendum_);
|
||||
return reinterpret_cast<TypeNewScript *>(addendum_);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -313,7 +233,7 @@ class ObjectGroup : public gc::TenuredCell
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
types::TypeNewScript *anyNewScript();
|
||||
TypeNewScript *anyNewScript();
|
||||
void detachNewScript(bool writeBarrier);
|
||||
|
||||
public:
|
||||
|
@ -333,12 +253,12 @@ class ObjectGroup : public gc::TenuredCell
|
|||
flags_ &= ~flags;
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScript() {
|
||||
TypeNewScript *newScript() {
|
||||
maybeSweep(nullptr);
|
||||
return newScriptDontCheckGeneration();
|
||||
}
|
||||
|
||||
void setNewScript(types::TypeNewScript *newScript) {
|
||||
void setNewScript(TypeNewScript *newScript) {
|
||||
setAddendum(Addendum_NewScript, newScript);
|
||||
}
|
||||
|
||||
|
@ -385,13 +305,71 @@ class ObjectGroup : public gc::TenuredCell
|
|||
setAddendum(Addendum_InterpretedFunction, fun);
|
||||
}
|
||||
|
||||
class Property
|
||||
{
|
||||
public:
|
||||
// Identifier for this property, JSID_VOID for the aggregate integer
|
||||
// index property, or JSID_EMPTY for properties holding constraints
|
||||
// listening to changes in the group's state.
|
||||
HeapId id;
|
||||
|
||||
// Possible own types for this property.
|
||||
HeapTypeSet types;
|
||||
|
||||
explicit Property(jsid id)
|
||||
: id(id)
|
||||
{}
|
||||
|
||||
Property(const Property &o)
|
||||
: id(o.id.get()), types(o.types)
|
||||
{}
|
||||
|
||||
static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
|
||||
static jsid getKey(Property *p) { return p->id; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Properties of this object. This may contain JSID_VOID, representing the
|
||||
// types of all integer indexes of the object, and/or JSID_EMPTY, holding
|
||||
// constraints listening to changes to the object's state.
|
||||
//
|
||||
// See types::Property for more detail about the types represented here.
|
||||
types::Property **propertySet;
|
||||
/*
|
||||
* Properties of this object.
|
||||
*
|
||||
* The type sets in the properties of a group describe the possible values
|
||||
* that can be read out of that property in actual JS objects. In native
|
||||
* objects, property types account for plain data properties (those with a
|
||||
* slot and no getter or setter hook) and dense elements. In typed objects
|
||||
* and unboxed objects, property types account for object and value
|
||||
* properties and elements in the object.
|
||||
*
|
||||
* For accesses on these properties, the correspondence is as follows:
|
||||
*
|
||||
* 1. If the group has unknownProperties(), the possible properties and
|
||||
* value types for associated JSObjects are unknown.
|
||||
*
|
||||
* 2. Otherwise, for any |obj| in |group|, and any |id| which is a property
|
||||
* in |obj|, before obj->getProperty(id) the property in |group| for
|
||||
* |id| must reflect the result of the getProperty.
|
||||
*
|
||||
* There are several exceptions to this:
|
||||
*
|
||||
* 1. For properties of global JS objects which are undefined at the point
|
||||
* where the property was (lazily) generated, the property type set will
|
||||
* remain empty, and the 'undefined' type will only be added after a
|
||||
* subsequent assignment or deletion. After these properties have been
|
||||
* assigned a defined value, the only way they can become undefined
|
||||
* again is after such an assign or deletion.
|
||||
*
|
||||
* 2. Array lengths are special cased by the compiler and VM and are not
|
||||
* reflected in property types.
|
||||
*
|
||||
* 3. In typed objects (but not unboxed objects), the initial values of
|
||||
* properties (null pointers and undefined values) are not reflected in
|
||||
* the property types. These values are always possible when reading the
|
||||
* property.
|
||||
*
|
||||
* We establish these by using write barriers on calls to setProperty and
|
||||
* defineProperty which are on native properties, and on any jitcode which
|
||||
* might update the property with a new type.
|
||||
*/
|
||||
Property **propertySet;
|
||||
public:
|
||||
|
||||
inline ObjectGroup(const Class *clasp, TaggedProto proto, ObjectGroupFlags initialFlags);
|
||||
|
@ -415,7 +393,7 @@ class ObjectGroup : public gc::TenuredCell
|
|||
return hasAnyFlags(OBJECT_FLAG_PRE_TENURE) && !unknownProperties();
|
||||
}
|
||||
|
||||
gc::InitialHeap initialHeap(types::CompilerConstraintList *constraints);
|
||||
gc::InitialHeap initialHeap(CompilerConstraintList *constraints);
|
||||
|
||||
bool canPreTenure() {
|
||||
return !unknownProperties();
|
||||
|
@ -434,17 +412,17 @@ class ObjectGroup : public gc::TenuredCell
|
|||
* Get or create a property of this object. Only call this for properties which
|
||||
* a script accesses explicitly.
|
||||
*/
|
||||
inline types::HeapTypeSet *getProperty(ExclusiveContext *cx, jsid id);
|
||||
inline HeapTypeSet *getProperty(ExclusiveContext *cx, jsid id);
|
||||
|
||||
/* Get a property only if it already exists. */
|
||||
inline types::HeapTypeSet *maybeGetProperty(jsid id);
|
||||
inline HeapTypeSet *maybeGetProperty(jsid id);
|
||||
|
||||
inline unsigned getPropertyCount();
|
||||
inline types::Property *getProperty(unsigned i);
|
||||
inline Property *getProperty(unsigned i);
|
||||
|
||||
/* Helpers */
|
||||
|
||||
void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, types::HeapTypeSet *types);
|
||||
void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types);
|
||||
bool addDefiniteProperties(ExclusiveContext *cx, Shape *shape);
|
||||
bool matchDefiniteProperties(HandleObject obj);
|
||||
void markPropertyNonData(ExclusiveContext *cx, jsid id);
|
||||
|
@ -460,7 +438,7 @@ class ObjectGroup : public gc::TenuredCell
|
|||
void print();
|
||||
|
||||
inline void clearProperties();
|
||||
void maybeSweep(types::AutoClearTypeInferenceStateOnOOM *oom);
|
||||
void maybeSweep(AutoClearTypeInferenceStateOnOOM *oom);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
|
@ -568,12 +546,13 @@ class ObjectGroup : public gc::TenuredCell
|
|||
static ArrayObject *getCopyOnWriteObject(JSScript *script, jsbytecode *pc);
|
||||
|
||||
// Returns false if not found.
|
||||
static bool findAllocationSiteForType(JSContext *cx, types::Type type,
|
||||
static bool findAllocationSite(JSContext *cx, ObjectGroup *group,
|
||||
JSScript **script, uint32_t *offset);
|
||||
|
||||
private:
|
||||
static ObjectGroup *defaultNewGroup(JSContext *cx, JSProtoKey key);
|
||||
static void setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj, types::Type type);
|
||||
static void setGroupToHomogenousArray(ExclusiveContext *cx, JSObject *obj,
|
||||
TypeSet::Type type);
|
||||
};
|
||||
|
||||
// Structure used to manage the groups in a compartment.
|
||||
|
|
|
@ -66,7 +66,7 @@ ProxyObject::New(JSContext *cx, const BaseProxyHandler *handler, HandleValue pri
|
|||
|
||||
/* Don't track types of properties of non-DOM and non-singleton proxies. */
|
||||
if (newKind != SingletonObject && !clasp->isDOMClass())
|
||||
types::MarkObjectGroupUnknownProperties(cx, proxy->group());
|
||||
MarkObjectGroupUnknownProperties(cx, proxy->group());
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
|
|
@ -738,8 +738,8 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext *cx)
|
|||
|
||||
// Make sure type information reflects the indexed properties which might
|
||||
// be added.
|
||||
types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::StringType());
|
||||
types::AddTypePropertyId(cx, templateObject, JSID_VOID, types::Type::UndefinedType());
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType());
|
||||
AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
|
||||
|
||||
matchResultTemplateObject_.set(templateObject);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ RegExpStatics::markFlagsSet(JSContext *cx)
|
|||
// always be performed).
|
||||
MOZ_ASSERT_IF(cx->global()->hasRegExpStatics(), this == cx->global()->getRegExpStatics(cx));
|
||||
|
||||
types::MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_REGEXP_FLAGS_SET);
|
||||
MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_REGEXP_FLAGS_SET);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -24,7 +24,7 @@ ScopeObject::setAliasedVar(JSContext *cx, ScopeCoordinate sc, PropertyName *name
|
|||
|
||||
if (isSingleton()) {
|
||||
MOZ_ASSERT(name);
|
||||
types::AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
|
||||
// Keep track of properties which have ever been overwritten.
|
||||
if (!getSlot(sc.slot()).isUndefined()) {
|
||||
|
@ -42,7 +42,7 @@ CallObject::setAliasedVar(JSContext *cx, AliasedFormalIter fi, PropertyName *nam
|
|||
MOZ_ASSERT(name == fi->name());
|
||||
setSlot(fi.scopeSlot(), v);
|
||||
if (isSingleton())
|
||||
types::AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(name), v);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -50,7 +50,7 @@ CallObject::setAliasedVarFromArguments(JSContext *cx, const Value &argsValue, js
|
|||
{
|
||||
setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
|
||||
if (isSingleton())
|
||||
types::AddTypePropertyId(cx, this, id, v);
|
||||
AddTypePropertyId(cx, this, id, v);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::PodZero;
|
||||
|
||||
|
|
|
@ -893,7 +893,7 @@ NativeObject::changeProperty(ExclusiveContext *cx, HandleNativeObject obj,
|
|||
MOZ_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
|
||||
!(attrs & JSPROP_SHARED));
|
||||
|
||||
types::MarkTypePropertyNonData(cx, obj, shape->propid());
|
||||
MarkTypePropertyNonData(cx, obj, shape->propid());
|
||||
|
||||
if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
|
||||
return nullptr;
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::NegativeInfinity;
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
using namespace js::types;
|
||||
|
||||
using mozilla::IsNaN;
|
||||
using mozilla::NegativeInfinity;
|
||||
|
|
|
@ -42,10 +42,10 @@ UnboxedLayout::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
|||
}
|
||||
|
||||
void
|
||||
UnboxedLayout::setNewScript(types::TypeNewScript *newScript, bool writeBarrier /* = true */)
|
||||
UnboxedLayout::setNewScript(TypeNewScript *newScript, bool writeBarrier /* = true */)
|
||||
{
|
||||
if (newScript_ && writeBarrier)
|
||||
types::TypeNewScript::writeBarrierPre(newScript_);
|
||||
TypeNewScript::writeBarrierPre(newScript_);
|
||||
newScript_ = newScript;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ UnboxedPlainObject::setValue(JSContext *cx, const UnboxedLayout::Property &prope
|
|||
// Update property types when writing object properties. Types for
|
||||
// other properties were captured when the unboxed layout was
|
||||
// created.
|
||||
types::AddTypePropertyId(cx, this, NameToId(property.name), v);
|
||||
AddTypePropertyId(cx, this, NameToId(property.name), v);
|
||||
|
||||
*reinterpret_cast<HeapPtrObject*>(p) = v.toObjectOrNull();
|
||||
return true;
|
||||
|
@ -440,7 +440,7 @@ PropertiesAreSuperset(const UnboxedLayout::PropertyVector &properties, UnboxedLa
|
|||
|
||||
bool
|
||||
js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
ObjectGroup *group, types::PreliminaryObjectArray *objects)
|
||||
ObjectGroup *group, PreliminaryObjectArray *objects)
|
||||
{
|
||||
if (!cx->runtime()->options().unboxedObjects())
|
||||
return true;
|
||||
|
@ -453,7 +453,7 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
|||
return false;
|
||||
|
||||
size_t objectCount = 0;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
JSObject *obj = objects->get(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
|
@ -625,7 +625,7 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
|||
Vector<Value, 0, SystemAllocPolicy> values;
|
||||
if (!values.reserve(objectCount * templateShape->slotSpan()))
|
||||
return false;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
if (!objects->get(i))
|
||||
continue;
|
||||
|
||||
|
@ -639,14 +639,14 @@ js::TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
|||
obj->setLastPropertyMakeNonNative(newShape);
|
||||
}
|
||||
|
||||
if (types::TypeNewScript *newScript = group->newScript())
|
||||
if (TypeNewScript *newScript = group->newScript())
|
||||
layout->setNewScript(newScript);
|
||||
|
||||
group->setClasp(&UnboxedPlainObject::class_);
|
||||
group->setUnboxedLayout(layout.get());
|
||||
|
||||
size_t valueCursor = 0;
|
||||
for (size_t i = 0; i < types::PreliminaryObjectArray::COUNT; i++) {
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
if (!objects->get(i))
|
||||
continue;
|
||||
UnboxedPlainObject *obj = &objects->get(i)->as<UnboxedPlainObject>();
|
||||
|
|
|
@ -58,7 +58,7 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
|
|||
size_t size_;
|
||||
|
||||
// Any 'new' script information associated with this layout.
|
||||
types::TypeNewScript *newScript_;
|
||||
TypeNewScript *newScript_;
|
||||
|
||||
// List for use in tracing objects with this layout. This has the same
|
||||
// structure as the trace list on a TypeDescr.
|
||||
|
@ -80,11 +80,11 @@ class UnboxedLayout : public mozilla::LinkedListElement<UnboxedLayout>
|
|||
return properties_;
|
||||
}
|
||||
|
||||
types::TypeNewScript *newScript() const {
|
||||
TypeNewScript *newScript() const {
|
||||
return newScript_;
|
||||
}
|
||||
|
||||
void setNewScript(types::TypeNewScript *newScript, bool writeBarrier = true);
|
||||
void setNewScript(TypeNewScript *newScript, bool writeBarrier = true);
|
||||
|
||||
const int32_t *traceList() const {
|
||||
return traceList_;
|
||||
|
@ -182,7 +182,7 @@ class UnboxedPlainObject : public JSObject
|
|||
// preliminary objects and their group to the new unboxed representation.
|
||||
bool
|
||||
TryConvertToUnboxedLayout(JSContext *cx, Shape *templateShape,
|
||||
ObjectGroup *group, types::PreliminaryObjectArray *objects);
|
||||
ObjectGroup *group, PreliminaryObjectArray *objects);
|
||||
|
||||
inline gc::AllocKind
|
||||
UnboxedLayout::getAllocKind() const
|
||||
|
|
Загрузка…
Ссылка в новой задаче