Merge inbound to mozilla-central. a=merge

This commit is contained in:
Ciure Andrei 2019-02-01 19:56:27 +02:00
Родитель 15907fc6e1 0deb9fd9cb
Коммит 71db6522be
53 изменённых файлов: 1188 добавлений и 578 удалений

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

@ -123,7 +123,7 @@ NS_IMPL_RELEASE_INHERITED(ModuleScript, LoadedScript)
ModuleScript::ModuleScript(ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
: LoadedScript(ScriptKind::eModule, aFetchOptions, aBaseURL),
mSourceElementAssociated(false) {
mDebuggerDataInitialized(false) {
MOZ_ASSERT(!ModuleRecord());
MOZ_ASSERT(!HasParseError());
MOZ_ASSERT(!HasErrorToRethrow());
@ -182,11 +182,11 @@ void ModuleScript::SetErrorToRethrow(const JS::Value& aError) {
mErrorToRethrow = aError;
}
void ModuleScript::SetSourceElementAssociated() {
void ModuleScript::SetDebuggerDataInitialized() {
MOZ_ASSERT(ModuleRecord());
MOZ_ASSERT(!mSourceElementAssociated);
MOZ_ASSERT(!mDebuggerDataInitialized);
mSourceElementAssociated = true;
mDebuggerDataInitialized = true;
}
} // namespace dom

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

@ -64,7 +64,7 @@ class ModuleScript final : public LoadedScript {
JS::Heap<JSObject*> mModuleRecord;
JS::Heap<JS::Value> mParseError;
JS::Heap<JS::Value> mErrorToRethrow;
bool mSourceElementAssociated;
bool mDebuggerDataInitialized;
~ModuleScript();
@ -78,7 +78,7 @@ class ModuleScript final : public LoadedScript {
void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
void SetParseError(const JS::Value& aError);
void SetErrorToRethrow(const JS::Value& aError);
void SetSourceElementAssociated();
void SetDebuggerDataInitialized();
JSObject* ModuleRecord() const { return mModuleRecord; }
@ -86,7 +86,7 @@ class ModuleScript final : public LoadedScript {
JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
bool HasParseError() const { return !mParseError.isUndefined(); }
bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
bool SourceElementAssociated() const { return mSourceElementAssociated; }
bool DebuggerDataInitialized() const { return mDebuggerDataInitialized; }
void UnlinkModuleRecord();

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

@ -1108,21 +1108,22 @@ bool ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest) {
return true;
}
nsresult ScriptLoader::AssociateSourceElementsForModuleTree(
nsresult ScriptLoader::InitDebuggerDataForModuleTree(
JSContext* aCx, ModuleLoadRequest* aRequest) {
// Preloading can cause JS scripts to be compiled before DOM script element
// nodes have been created. This method ensures compiled scripts are
// associated with DOM element nodes before execution.
// JS scripts can be associated with a DOM element for use by the debugger,
// but preloading can cause scripts to be compiled before DOM script element
// nodes have been created. This method ensures that this association takes
// place before the first time a module script is run.
MOZ_ASSERT(aRequest);
ModuleScript* moduleScript = aRequest->mModuleScript;
if (moduleScript->SourceElementAssociated()) {
if (moduleScript->DebuggerDataInitialized()) {
return NS_OK;
}
for (ModuleLoadRequest* childRequest : aRequest->mImports) {
nsresult rv = AssociateSourceElementsForModuleTree(aCx, childRequest);
nsresult rv = InitDebuggerDataForModuleTree(aCx, childRequest);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1133,13 +1134,13 @@ nsresult ScriptLoader::AssociateSourceElementsForModuleTree(
if (element) {
nsresult rv = nsJSUtils::InitModuleSourceElement(aCx, module, element);
NS_ENSURE_SUCCESS(rv, rv);
moduleScript->SetSourceElementAssociated();
}
// The script is now ready to be exposed to the debugger.
JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(module));
JS::ExposeScriptToDebugger(aCx, script);
moduleScript->SetDebuggerDataInitialized();
return NS_OK;
}
@ -2576,10 +2577,8 @@ nsresult ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest) {
JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
MOZ_ASSERT(module);
if (!moduleScript->SourceElementAssociated()) {
rv = AssociateSourceElementsForModuleTree(cx, request);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = InitDebuggerDataForModuleTree(cx, request);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsJSUtils::ModuleEvaluate(cx, module);
MOZ_ASSERT(NS_FAILED(rv) == aes.HasException());

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

@ -524,8 +524,8 @@ class ScriptLoader final : public nsISupports {
RefPtr<mozilla::GenericPromise> StartFetchingModuleAndDependencies(
ModuleLoadRequest* aParent, nsIURI* aURI);
nsresult AssociateSourceElementsForModuleTree(JSContext* aCx,
ModuleLoadRequest* aRequest);
nsresult InitDebuggerDataForModuleTree(JSContext* aCx,
ModuleLoadRequest* aRequest);
void RunScriptWhenSafe(ScriptLoadRequest* aRequest);

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

@ -34,7 +34,7 @@ enum class GamepadCapabilityFlags : uint16_t;
#endif // MOZILLA_INTERNAL_API
namespace gfx {
static const int32_t kVRExternalVersion = 5;
static const int32_t kVRExternalVersion = 6;
// We assign VR presentations to groups with a bitmask.
// Currently, we will only display either content or chrome.
@ -390,20 +390,25 @@ struct VRExternalShmem {
int32_t size;
#if defined(__ANDROID__)
pthread_mutex_t systemMutex;
pthread_mutex_t browserMutex;
pthread_mutex_t geckoMutex;
pthread_mutex_t servoMutex;
pthread_cond_t systemCond;
pthread_cond_t browserCond;
pthread_cond_t geckoCond;
pthread_cond_t servoCond;
#else
int64_t generationA;
#endif // defined(__ANDROID__)
VRSystemState state;
#if !defined(__ANDROID__)
int64_t generationB;
int64_t browserGenerationA;
int64_t geckoGenerationA;
int64_t servoGenerationA;
#endif // !defined(__ANDROID__)
VRBrowserState browserState;
VRBrowserState geckoState;
VRBrowserState servoState;
#if !defined(__ANDROID__)
int64_t browserGenerationB;
int64_t geckoGenerationB;
int64_t servoGenerationB;
#endif // !defined(__ANDROID__)
};

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

@ -870,14 +870,14 @@ void VRSystemManagerExternal::PushState(VRBrowserState* aBrowserState,
MOZ_ASSERT(mExternalShmem);
if (mExternalShmem) {
#if defined(MOZ_WIDGET_ANDROID)
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->browserMutex)) ==
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->geckoMutex)) ==
0) {
memcpy((void*)&(mExternalShmem->browserState), aBrowserState,
memcpy((void*)&(mExternalShmem->geckoState), aBrowserState,
sizeof(VRBrowserState));
if (aNotifyCond) {
pthread_cond_signal((pthread_cond_t*)&(mExternalShmem->browserCond));
pthread_cond_signal((pthread_cond_t*)&(mExternalShmem->geckoCond));
}
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->browserMutex));
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->geckoMutex));
}
#else
bool status = true;
@ -886,13 +886,13 @@ void VRSystemManagerExternal::PushState(VRBrowserState* aBrowserState,
status = lock.GetStatus();
#endif // defined(XP_WIN)
if (status) {
mExternalShmem->browserGenerationA++;
memcpy((void*)&(mExternalShmem->browserState), (void*)aBrowserState,
mExternalShmem->geckoGenerationA++;
memcpy((void*)&(mExternalShmem->geckoState), (void*)aBrowserState,
sizeof(VRBrowserState));
mExternalShmem->browserGenerationB++; mExternalShmem->browserGenerationA++;
memcpy((void*)&(mExternalShmem->browserState), (void*)aBrowserState,
mExternalShmem->geckoGenerationB++; mExternalShmem->geckoGenerationA++;
memcpy((void*)&(mExternalShmem->geckoState), (void*)aBrowserState,
sizeof(VRBrowserState));
mExternalShmem->browserGenerationB++;
mExternalShmem->geckoGenerationB++;
}
#endif // defined(MOZ_WIDGET_ANDROID)
}

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

@ -478,15 +478,15 @@ void VRService::PullState(mozilla::gfx::VRBrowserState& aState) {
// locked for the duration of the memcpy to and from shmem on
// both sides.
// On x86/x64 It is fallable -- If a dirty copy is detected by
// a mismatch of browserGenerationA and browserGenerationB,
// a mismatch of geckoGenerationA and geckoGenerationB,
// the copy is discarded and will not replace the last known
// browser state.
#if defined(MOZ_WIDGET_ANDROID)
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->browserMutex)) ==
if (pthread_mutex_lock((pthread_mutex_t*)&(mExternalShmem->geckoMutex)) ==
0) {
memcpy(&aState, &tmp.browserState, sizeof(VRBrowserState));
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->browserMutex));
memcpy(&aState, &tmp.geckoState, sizeof(VRBrowserState));
pthread_mutex_unlock((pthread_mutex_t*)&(mExternalShmem->geckoMutex));
}
#else
bool status = true;
@ -496,12 +496,12 @@ void VRService::PullState(mozilla::gfx::VRBrowserState& aState) {
#endif // defined(XP_WIN)
if (status) {
VRExternalShmem tmp;
if (mAPIShmem->browserGenerationA != mBrowserGeneration) {
if (mAPIShmem->geckoGenerationA != mBrowserGeneration) {
memcpy(&tmp, mAPIShmem, sizeof(VRExternalShmem));
if (tmp.browserGenerationA == tmp.browserGenerationB &&
tmp.browserGenerationA != 0 && tmp.browserGenerationA != -1) {
memcpy(&aState, &tmp.browserState, sizeof(VRBrowserState));
mBrowserGeneration = tmp.browserGenerationA;
if (tmp.geckoGenerationA == tmp.geckoGenerationB &&
tmp.geckoGenerationA != 0 && tmp.geckoGenerationA != -1) {
memcpy(&aState, &tmp.geckoState, sizeof(VRBrowserState));
mBrowserGeneration = tmp.geckoGenerationA;
}
}
}

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

@ -801,8 +801,8 @@ static const uint32_t JSCLASS_RESERVED_SLOTS_MASK =
#define JSCLASS_HIGH_FLAGS_SHIFT \
(JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH)
static const uint32_t JSCLASS_IS_ANONYMOUS = 1
<< (JSCLASS_HIGH_FLAGS_SHIFT + 0);
static const uint32_t JSCLASS_INTERNAL_FLAG1 =
1 << (JSCLASS_HIGH_FLAGS_SHIFT + 0);
static const uint32_t JSCLASS_IS_GLOBAL = 1 << (JSCLASS_HIGH_FLAGS_SHIFT + 1);
static const uint32_t JSCLASS_INTERNAL_FLAG2 =
1 << (JSCLASS_HIGH_FLAGS_SHIFT + 2);

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

@ -79,8 +79,7 @@ static bool ModuleValueGetter(JSContext* cx, unsigned argc, Value* vp) {
// ImportEntryObject
/* static */ const Class ImportEntryObject::class_ = {
"ImportEntry", JSCLASS_HAS_RESERVED_SLOTS(ImportEntryObject::SlotCount) |
JSCLASS_IS_ANONYMOUS};
"ImportEntry", JSCLASS_HAS_RESERVED_SLOTS(ImportEntryObject::SlotCount)};
DEFINE_GETTER_FUNCTIONS(ImportEntryObject, moduleRequest, ModuleRequestSlot)
DEFINE_GETTER_FUNCTIONS(ImportEntryObject, importName, ImportNameSlot)
@ -149,8 +148,7 @@ DEFINE_UINT32_ACCESSOR_METHOD(ImportEntryObject, columnNumber)
// ExportEntryObject
/* static */ const Class ExportEntryObject::class_ = {
"ExportEntry", JSCLASS_HAS_RESERVED_SLOTS(ExportEntryObject::SlotCount) |
JSCLASS_IS_ANONYMOUS};
"ExportEntry", JSCLASS_HAS_RESERVED_SLOTS(ExportEntryObject::SlotCount)};
DEFINE_GETTER_FUNCTIONS(ExportEntryObject, exportName, ExportNameSlot)
DEFINE_GETTER_FUNCTIONS(ExportEntryObject, moduleRequest, ModuleRequestSlot)
@ -233,8 +231,7 @@ static Value StringOrNullValue(JSString* maybeString) {
/* static */ const Class RequestedModuleObject::class_ = {
"RequestedModule",
JSCLASS_HAS_RESERVED_SLOTS(RequestedModuleObject::SlotCount) |
JSCLASS_IS_ANONYMOUS};
JSCLASS_HAS_RESERVED_SLOTS(RequestedModuleObject::SlotCount)};
DEFINE_GETTER_FUNCTIONS(RequestedModuleObject, moduleSpecifier,
ModuleSpecifierSlot)
@ -692,7 +689,7 @@ void FunctionDeclaration::trace(JSTracer* trc) {
/* static */ const Class ModuleObject::class_ = {
"Module",
JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) | JSCLASS_IS_ANONYMOUS |
JSCLASS_HAS_RESERVED_SLOTS(ModuleObject::SlotCount) |
JSCLASS_BACKGROUND_FINALIZE,
&ModuleObject::classOps_};

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

@ -2299,8 +2299,7 @@ static const JSClassOps FinalizeCounterClassOps = {nullptr, /* addProperty */
finalize_counter_finalize};
static const JSClass FinalizeCounterClass = {
"FinalizeCounter", JSCLASS_IS_ANONYMOUS | JSCLASS_FOREGROUND_FINALIZE,
&FinalizeCounterClassOps};
"FinalizeCounter", JSCLASS_FOREGROUND_FINALIZE, &FinalizeCounterClassOps};
static bool MakeFinalizeObserver(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);

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

@ -1506,6 +1506,26 @@ function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) {
if (!IsCallable(usingIterator))
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, source));
// Try to take a fast path when there's no mapper function and the
// constructor is a built-in TypedArray constructor.
if (!mapping && IsTypedArrayConstructor(C)) {
// TODO: Add fast path for TypedArray inputs (bug 1491813).
// The source is a packed array using the default iterator.
if (usingIterator === ArrayValues && IsPackedArray(source) &&
ArrayIteratorPrototypeOptimizable())
{
// Steps 7.b-c.
var targetObj = new C(source.length);
// Steps 7.a, 7.d-f.
TypedArrayInitFromPackedArray(targetObj, source);
// Step 7.g.
return targetObj;
}
}
// Step 7.a.
var values = IterableToList(source, usingIterator);
@ -1598,21 +1618,6 @@ function TypedArraySpecies() {
}
_SetCanonicalName(TypedArraySpecies, "get [Symbol.species]");
// ES 2017 draft June 2, 2016 22.2.3.32
function TypedArrayToStringTag() {
// Step 1.
var O = this;
// Steps 2-3.
if (!IsObject(O) || !IsPossiblyWrappedTypedArray(O))
return undefined;
// Steps 4-6.
// Modified to retrieve the [[TypedArrayName]] from the constructor.
return _NameForTypedArray(O);
}
_SetCanonicalName(TypedArrayToStringTag, "get [Symbol.toStringTag]");
// ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c
// 22.2.2.1.1 Runtime Semantics: IterableToList( items, method )
function IterableToList(items, method) {

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

@ -72,7 +72,6 @@ enum class DeclarationKind : uint8_t {
FormalParameter,
CoverArrowParameter,
Var,
ForOfVar,
Let,
Const,
Class, // Handled as same as `let` after parsing.
@ -97,7 +96,6 @@ static inline BindingKind DeclarationKindToBindingKind(DeclarationKind kind) {
case DeclarationKind::BodyLevelFunction:
case DeclarationKind::ModuleBodyLevelFunction:
case DeclarationKind::VarForAnnexBLexicalFunction:
case DeclarationKind::ForOfVar:
return BindingKind::Var;
case DeclarationKind::Let:

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

@ -40,8 +40,6 @@ const char* DeclarationKindString(DeclarationKind kind) {
return "function";
case DeclarationKind::VarForAnnexBLexicalFunction:
return "annex b var";
case DeclarationKind::ForOfVar:
return "var in for-of";
case DeclarationKind::SimpleCatchParameter:
case DeclarationKind::CatchParameter:
return "catch parameter";
@ -53,8 +51,7 @@ const char* DeclarationKindString(DeclarationKind kind) {
bool DeclarationKindIsVar(DeclarationKind kind) {
return kind == DeclarationKind::Var ||
kind == DeclarationKind::BodyLevelFunction ||
kind == DeclarationKind::VarForAnnexBLexicalFunction ||
kind == DeclarationKind::ForOfVar;
kind == DeclarationKind::VarForAnnexBLexicalFunction;
}
bool DeclarationKindIsParameter(DeclarationKind kind) {
@ -359,10 +356,8 @@ Maybe<DeclarationKind> ParseContext::isVarRedeclaredInEval(
switch (bi.kind()) {
case BindingKind::Let: {
// Annex B.3.5 allows redeclaring simple (non-destructured)
// catch parameters with var declarations, except when it
// appears in a for-of.
bool annexB35Allowance = si.kind() == ScopeKind::SimpleCatch &&
kind != DeclarationKind::ForOfVar;
// catch parameters with var declarations.
bool annexB35Allowance = si.kind() == ScopeKind::SimpleCatch;
if (!annexB35Allowance) {
return Some(ScopeKindIsCatch(si.kind())
? DeclarationKind::CatchParameter
@ -434,13 +429,6 @@ bool ParseContext::tryDeclareVarHelper(HandlePropertyName name,
// restrictive kind. These semantics are implemented in
// CheckCanDeclareGlobalBinding.
//
// For a var previously declared as ForOfVar, this previous
// DeclarationKind is used only to check for if the
// 'arguments' binding should be declared. Since body-level
// functions shadow 'arguments' [5], it is correct to alter
// the kind to BodyLevelFunction. See
// declareFunctionArgumentsObject.
//
// VarForAnnexBLexicalFunction declarations are declared when
// the var scope exits. It is not possible for a var to be
// previously declared as VarForAnnexBLexicalFunction and
@ -450,7 +438,6 @@ bool ParseContext::tryDeclareVarHelper(HandlePropertyName name,
// [2] ES 18.2.1.3
// [3] ES 8.1.1.4.15
// [4] ES 8.1.1.4.16
// [5] ES 9.2.12
if (dryRunOption == NotDryRun &&
kind == DeclarationKind::BodyLevelFunction) {
MOZ_ASSERT(declaredKind !=
@ -459,11 +446,9 @@ bool ParseContext::tryDeclareVarHelper(HandlePropertyName name,
}
} else if (!DeclarationKindIsParameter(declaredKind)) {
// Annex B.3.5 allows redeclaring simple (non-destructured)
// catch parameters with var declarations, except when it
// appears in a for-of.
// catch parameters with var declarations.
bool annexB35Allowance =
declaredKind == DeclarationKind::SimpleCatchParameter &&
kind != DeclarationKind::ForOfVar;
declaredKind == DeclarationKind::SimpleCatchParameter;
// Annex B.3.3 allows redeclaring functions in the same block.
bool annexB33Allowance =

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

@ -608,8 +608,7 @@ bool GeneralParser<ParseHandler, Unit>::noteDeclaredName(
switch (kind) {
case DeclarationKind::Var:
case DeclarationKind::BodyLevelFunction:
case DeclarationKind::ForOfVar: {
case DeclarationKind::BodyLevelFunction: {
Maybe<DeclarationKind> redeclaredKind;
uint32_t prevPos;
if (!pc->tryDeclareVar(name, kind, pos.begin, &redeclaredKind,
@ -1882,8 +1881,7 @@ bool PerHandlerParser<ParseHandler>::declareFunctionArgumentsObject() {
// declared 'var arguments', we still need to declare 'arguments' in the
// function scope.
DeclaredNamePtr p = varScope.lookupDeclaredName(argumentsName);
if (p && (p->value()->kind() == DeclarationKind::Var ||
p->value()->kind() == DeclarationKind::ForOfVar)) {
if (p && p->value()->kind() == DeclarationKind::Var) {
if (hasExtraBodyVarScope) {
tryDeclareArguments = true;
} else {
@ -4154,11 +4152,6 @@ GeneralParser<ParseHandler, Unit>::declarationPattern(
*forHeadKind = ParseNodeKind::ForIn;
} else if (isForOf) {
*forHeadKind = ParseNodeKind::ForOf;
// Annex B.3.5 has different early errors for vars in for-of loops.
if (declKind == DeclarationKind::Var) {
declKind = DeclarationKind::ForOfVar;
}
} else {
*forHeadKind = ParseNodeKind::ForHead;
}
@ -4306,11 +4299,6 @@ GeneralParser<ParseHandler, Unit>::declarationName(DeclarationKind declKind,
*forHeadKind = ParseNodeKind::ForIn;
} else if (isForOf) {
*forHeadKind = ParseNodeKind::ForOf;
// Annex B.3.5 has different early errors for vars in for-of loops.
if (declKind == DeclarationKind::Var) {
declKind = DeclarationKind::ForOfVar;
}
} else {
*forHeadKind = ParseNodeKind::ForHead;
}

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

@ -0,0 +1,165 @@
// Test TypedArray constructor when called with iterables or typed arrays.
function testPackedArray() {
function test() {
var array = [
1, 2, 3,
4, 5, 6,
7, 8, 9,
];
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testPackedArray();
function testHoleArray() {
function test() {
var array = [
1, /* hole */, 3,
4, /* hole */, 6,
7, /* hole */, 9,
];
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j] || 0);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testHoleArray();
function testTypedArraySameType() {
function test() {
var array = new Int32Array([
1, 2, 3,
4, 5, 6,
7, 8, 9,
]);
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testTypedArraySameType();
function testTypedArrayDifferentType() {
function test() {
var array = new Float32Array([
1, 2, 3,
4, 5, 6,
7, 8, 9,
]);
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testTypedArrayDifferentType();
function testIterable() {
function test() {
var array = [
1, 2, 3,
4, 5, 6,
7, 8, 9,
];
array = Object.defineProperties({
[Symbol.iterator]() {
var index = 0;
return {
next() {
var done = index >= array.length;
var value = !done ? array[index++] : undefined;
return {done, value};
}
};
}
}, Object.getOwnPropertyDescriptors(array));
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testIterable();
function testWrappedArray() {
var g = newGlobal();
function test() {
var array = new g.Array(
1, 2, 3,
4, 5, 6,
7, 8, 9,
);
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testWrappedArray();
function testWrappedTypedArray() {
var g = newGlobal();
function test() {
var array = new g.Int32Array([
1, 2, 3,
4, 5, 6,
7, 8, 9,
]);
for (var i = 0; i < 1000; ++i) {
var ta = new Int32Array(array);
assertEq(ta.length, array.length);
for (var j = 0; j < array.length; ++j) {
assertEq(ta[j], array[j]);
}
}
}
for (var i = 0; i < 2; ++i) {
test();
}
}
testWrappedTypedArray();

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

@ -0,0 +1,50 @@
var invalidatedFunction = function() { return false; }
var counter = 0;
function maybeInvalidate(iplusk) {
if (iplusk === 0) {
// This should happen only once; it will invalidate the call frame of
// the ion() function, which should rewind to just after the wasm call
// (if it got its own resume point).
// Before the patch, the wasm call doesn't get its resume point, so
// it's repeated and the importedFunc() is called once too many.
counter++;
invalidatedFunction = function () { return true; };
}
}
function importedFunc(k) {
for (let i = 100; i --> 0 ;) {
maybeInvalidate(i + k);
}
}
let { exports } = new WebAssembly.Instance(
new WebAssembly.Module(
wasmTextToBinary(`
(module
(func $imp (import "env" "importedFunc") (param i32))
(func (export "exp") (param i32)
get_local 0
call $imp
)
)
`)
), {
env: {
importedFunc
}
}
);
function ion(k) {
exports.exp(k);
invalidatedFunction();
}
for (let k = 100; k --> 0 ;) {
ion(k);
}
assertEq(counter, 1);

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

@ -3301,86 +3301,94 @@ static bool TryAttachFunCallStub(JSContext* cx, ICCall_Fallback* stub,
static bool GetTemplateObjectForNative(JSContext* cx, HandleFunction target,
const CallArgs& args,
MutableHandleObject res) {
Native native = target->native();
if (!target->hasJitInfo() ||
target->jitInfo()->type() != JSJitInfo::InlinableNative) {
return true;
}
// Check for natives to which template objects can be attached. This is
// done to provide templates to Ion for inlining these natives later on.
switch (target->jitInfo()->inlinableNative) {
case InlinableNative::Array: {
// Note: the template array won't be used if its length is inaccurately
// computed here. (We allocate here because compilation may occur on a
// separate thread where allocation is impossible.)
size_t count = 0;
if (args.length() != 1) {
count = args.length();
} else if (args.length() == 1 && args[0].isInt32() &&
args[0].toInt32() >= 0) {
count = args[0].toInt32();
}
if (native == ArrayConstructor || native == array_construct) {
// Note: the template array won't be used if its length is inaccurately
// computed here. (We allocate here because compilation may occur on a
// separate thread where allocation is impossible.)
size_t count = 0;
if (args.length() != 1) {
count = args.length();
} else if (args.length() == 1 && args[0].isInt32() &&
args[0].toInt32() >= 0) {
count = args[0].toInt32();
}
if (count > ArrayObject::EagerAllocationMaxLength) {
return true;
}
if (count <= ArrayObject::EagerAllocationMaxLength) {
// With this and other array templates, analyze the group so that
// we don't end up with a template whose structure might change later.
res.set(NewFullyAllocatedArrayForCallingAllocationSite(cx, count,
TenuredObject));
return !!res;
}
}
if (args.length() == 1) {
size_t len = 0;
if (args[0].isInt32() && args[0].toInt32() >= 0) {
len = args[0].toInt32();
}
if (!TypedArrayObject::GetTemplateObjectForNative(cx, native, len, res)) {
return false;
}
if (res) {
return true;
}
}
if (native == js::array_slice) {
if (args.thisv().isObject()) {
RootedObject obj(cx, &args.thisv().toObject());
if (!obj->isSingleton()) {
res.set(NewFullyAllocatedArrayTryReuseGroup(cx, obj, 0, TenuredObject));
return !!res;
case InlinableNative::ArraySlice: {
if (!args.thisv().isObject()) {
return true;
}
RootedObject obj(cx, &args.thisv().toObject());
if (obj->isSingleton()) {
return true;
}
res.set(NewFullyAllocatedArrayTryReuseGroup(cx, obj, 0, TenuredObject));
return !!res;
}
}
if (native == StringConstructor) {
RootedString emptyString(cx, cx->runtime()->emptyString);
res.set(StringObject::create(cx, emptyString, /* proto = */ nullptr,
TenuredObject));
return !!res;
}
case InlinableNative::String: {
RootedString emptyString(cx, cx->runtime()->emptyString);
res.set(StringObject::create(cx, emptyString, /* proto = */ nullptr,
TenuredObject));
return !!res;
}
if (native == obj_create && args.length() == 1 && args[0].isObjectOrNull()) {
RootedObject proto(cx, args[0].toObjectOrNull());
res.set(ObjectCreateImpl(cx, proto, TenuredObject));
return !!res;
}
case InlinableNative::ObjectCreate: {
if (args.length() != 1 || !args[0].isObjectOrNull()) {
return true;
}
RootedObject proto(cx, args[0].toObjectOrNull());
res.set(ObjectCreateImpl(cx, proto, TenuredObject));
return !!res;
}
if (native == js::intrinsic_NewArrayIterator) {
res.set(NewArrayIteratorObject(cx, TenuredObject));
return !!res;
}
case InlinableNative::IntrinsicNewArrayIterator: {
res.set(NewArrayIteratorObject(cx, TenuredObject));
return !!res;
}
if (native == js::intrinsic_NewStringIterator) {
res.set(NewStringIteratorObject(cx, TenuredObject));
return !!res;
}
case InlinableNative::IntrinsicNewStringIterator: {
res.set(NewStringIteratorObject(cx, TenuredObject));
return !!res;
}
if (native == js::intrinsic_NewRegExpStringIterator) {
res.set(NewRegExpStringIteratorObject(cx, TenuredObject));
return !!res;
}
case InlinableNative::IntrinsicNewRegExpStringIterator: {
res.set(NewRegExpStringIteratorObject(cx, TenuredObject));
return !!res;
}
return true;
case InlinableNative::TypedArrayConstructor: {
if (args.length() != 1) {
return true;
}
return TypedArrayObject::GetTemplateObjectForNative(cx, target->native(),
args[0], res);
}
default:
return true;
}
}
static bool GetTemplateObjectForClassHook(JSContext* cx, JSNative hook,

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

@ -6318,6 +6318,19 @@ void CodeGenerator::visitNewTypedArrayDynamicLength(
masm.bind(ool->rejoin());
}
typedef TypedArrayObject* (*TypedArrayCreateWithTemplateFn)(JSContext*,
HandleObject,
HandleObject);
static const VMFunction TypedArrayCreateWithTemplateInfo =
FunctionInfo<TypedArrayCreateWithTemplateFn>(
js::TypedArrayCreateWithTemplate, "TypedArrayCreateWithTemplate");
void CodeGenerator::visitNewTypedArrayFromArray(LNewTypedArrayFromArray* lir) {
pushArg(ToRegister(lir->array()));
pushArg(ImmGCPtr(lir->mir()->templateObject()));
callVM(TypedArrayCreateWithTemplateInfo, lir);
}
// Out-of-line object allocation for JSOP_NEWOBJECT.
class OutOfLineNewObject : public OutOfLineCodeBase<CodeGenerator> {
LNewObject* lir_;
@ -12593,10 +12606,21 @@ void CodeGenerator::visitIsArrayV(LIsArrayV* lir) {
EmitObjectIsArray(masm, ool, temp, output, &notArray);
}
typedef bool (*IsPossiblyWrappedTypedArrayFn)(JSContext*, JSObject*, bool*);
static const VMFunction IsPossiblyWrappedTypedArrayInfo =
FunctionInfo<IsPossiblyWrappedTypedArrayFn>(
jit::IsPossiblyWrappedTypedArray, "IsPossiblyWrappedTypedArray");
void CodeGenerator::visitIsTypedArray(LIsTypedArray* lir) {
Register object = ToRegister(lir->object());
Register output = ToRegister(lir->output());
OutOfLineCode* ool = nullptr;
if (lir->mir()->isPossiblyWrapped()) {
ool = oolCallVM(IsPossiblyWrappedTypedArrayInfo, lir, ArgList(object),
StoreRegisterTo(output));
}
Label notTypedArray;
Label done;
@ -12618,8 +12642,14 @@ void CodeGenerator::visitIsTypedArray(LIsTypedArray* lir) {
masm.move32(Imm32(1), output);
masm.jump(&done);
masm.bind(&notTypedArray);
if (ool) {
masm.branchTestClassIsProxy(true, output, ool->entry());
}
masm.move32(Imm32(0), output);
masm.bind(&done);
if (ool) {
masm.bind(ool->rejoin());
}
}
void CodeGenerator::visitIsObject(LIsObject* ins) {

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

@ -144,6 +144,7 @@
_(IntrinsicGuardToSharedArrayBuffer) \
\
_(TypedArrayConstructor) \
_(IntrinsicIsTypedArrayConstructor) \
_(IntrinsicIsTypedArray) \
_(IntrinsicIsPossiblyWrappedTypedArray) \
_(IntrinsicTypedArrayLength) \

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

@ -772,6 +772,7 @@ class IonBuilder : public MIRGenerator,
// TypedArray intrinsics.
enum WrappingBehavior { AllowWrappedTypedArrays, RejectWrappedTypedArrays };
InliningResult inlineTypedArray(CallInfo& callInfo, Native native);
InliningResult inlineIsTypedArrayConstructor(CallInfo& callInfo);
InliningResult inlineIsTypedArrayHelper(CallInfo& callInfo,
WrappingBehavior wrappingBehavior);
InliningResult inlineIsTypedArray(CallInfo& callInfo);

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

@ -21,11 +21,13 @@ using namespace js::jit;
void JSONSpewer::beginFunction(JSScript* script) {
beginObject();
if (script) {
formatProperty("name", "%s:%u", script->filename(), script->lineno());
} else {
property("name", "wasm compilation");
}
formatProperty("name", "%s:%u", script->filename(), script->lineno());
beginListProperty("passes");
}
void JSONSpewer::beginWasmFunction(unsigned funcIndex) {
beginObject();
formatProperty("name", "wasm-func%u", funcIndex);
beginListProperty("passes");
}

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

@ -28,6 +28,7 @@ class JSONSpewer : JSONPrinter {
explicit JSONSpewer(GenericPrinter& out) : JSONPrinter(out) {}
void beginFunction(JSScript* script);
void beginWasmFunction(unsigned funcIndex);
void beginPass(const char* pass);
void spewMDef(MDefinition* def);
void spewMResumePoint(MResumePoint* rp);

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

@ -245,9 +245,15 @@ void GraphSpewer::beginFunction(JSScript* function) {
if (!isSpewing()) {
return;
}
jsonSpewer_.beginFunction(function);
ionspewer.beginFunction();
}
void GraphSpewer::beginWasmFunction(unsigned funcIndex) {
if (!isSpewing()) {
return;
}
jsonSpewer_.beginWasmFunction(funcIndex);
ionspewer.beginFunction();
}
@ -321,6 +327,12 @@ void jit::SpewBeginFunction(MIRGenerator* mir, JSScript* function) {
mir->graphSpewer().beginFunction(function);
}
void jit::SpewBeginWasmFunction(MIRGenerator* mir, unsigned funcIndex) {
MIRGraph* graph = &mir->graph();
mir->graphSpewer().init(graph, nullptr);
mir->graphSpewer().beginWasmFunction(funcIndex);
}
AutoSpewEndFunction::~AutoSpewEndFunction() {
mir_->graphSpewer().endFunction();
}
@ -330,203 +342,181 @@ Fprinter& jit::JitSpewPrinter() {
return out;
}
static void PrintHelpAndExit(int status = 0) {
fflush(nullptr);
printf(
"\n"
"usage: IONFLAGS=option,option,option,... where options can be:\n"
"\n"
" aborts Compilation abort messages\n"
" scripts Compiled scripts\n"
" mir MIR information\n"
" prune Prune unused branches\n"
" escape Escape analysis\n"
" alias Alias analysis\n"
" alias-sum Alias analysis: shows summaries for every block\n"
" gvn Global Value Numbering\n"
" licm Loop invariant code motion\n"
" flac Fold linear arithmetic constants\n"
" eaa Effective address analysis\n"
" sincos Replace sin/cos by sincos\n"
" sink Sink transformation\n"
" regalloc Register allocation\n"
" inline Inlining\n"
" snapshots Snapshot information\n"
" codegen Native code generation\n"
" bailouts Bailouts\n"
" caches Inline caches\n"
" osi Invalidation\n"
" safepoints Safepoints\n"
" pools Literal Pools (ARM only for now)\n"
" cacheflush Instruction Cache flushes (ARM only for now)\n"
" range Range Analysis\n"
" logs JSON visualization logging\n"
" logs-sync Same as logs, but flushes between each pass (sync. "
"compiled functions only).\n"
" profiling Profiling-related information\n"
" trackopts Optimization tracking information gathered by the "
"Gecko profiler. "
"(Note: call enableGeckoProfiling() in your script to enable it).\n"
" trackopts-ext Encoding information about optimization tracking\n"
" dump-mir-expr Dump the MIR expressions\n"
" cfg Control flow graph generation\n"
" all Everything\n"
"\n"
" bl-aborts Baseline compiler abort messages\n"
" bl-scripts Baseline script-compilation\n"
" bl-op Baseline compiler detailed op-specific messages\n"
" bl-ic Baseline inline-cache messages\n"
" bl-ic-fb Baseline IC fallback stub messages\n"
" bl-osr Baseline IC OSR messages\n"
" bl-bails Baseline bailouts\n"
" bl-dbg-osr Baseline debug mode on stack recompile messages\n"
" bl-all All baseline spew\n"
"\n"
"See also SPEW=help for information on the Structured Spewer."
"\n");
exit(status);
}
static bool IsFlag(const char* found, const char* flag) {
return strlen(found) == strlen(flag) && strcmp(found, flag) == 0;
}
void jit::CheckLogging() {
if (LoggingChecked) {
return;
}
LoggingChecked = true;
const char* env = getenv("IONFLAGS");
char* env = getenv("IONFLAGS");
if (!env) {
return;
}
if (strstr(env, "help")) {
fflush(nullptr);
printf(
"\n"
"usage: IONFLAGS=option,option,option,... where options can be:\n"
"\n"
" aborts Compilation abort messages\n"
" scripts Compiled scripts\n"
" mir MIR information\n"
" prune Prune unused branches\n"
" escape Escape analysis\n"
" alias Alias analysis\n"
" alias-sum Alias analysis: shows summaries for every block\n"
" gvn Global Value Numbering\n"
" licm Loop invariant code motion\n"
" flac Fold linear arithmetic constants\n"
" eaa Effective address analysis\n"
" sincos Replace sin/cos by sincos\n"
" sink Sink transformation\n"
" regalloc Register allocation\n"
" inline Inlining\n"
" snapshots Snapshot information\n"
" codegen Native code generation\n"
" bailouts Bailouts\n"
" caches Inline caches\n"
" osi Invalidation\n"
" safepoints Safepoints\n"
" pools Literal Pools (ARM only for now)\n"
" cacheflush Instruction Cache flushes (ARM only for now)\n"
" range Range Analysis\n"
" logs JSON visualization logging\n"
" logs-sync Same as logs, but flushes between each pass (sync. "
"compiled functions only).\n"
" profiling Profiling-related information\n"
" trackopts Optimization tracking information gathered by the "
"Gecko profiler. "
"(Note: call enableGeckoProfiling() in your script to enable it).\n"
" trackopts-ext Encoding information about optimization tracking\n"
" dump-mir-expr Dump the MIR expressions\n"
" cfg Control flow graph generation\n"
" all Everything\n"
"\n"
" bl-aborts Baseline compiler abort messages\n"
" bl-scripts Baseline script-compilation\n"
" bl-op Baseline compiler detailed op-specific messages\n"
" bl-ic Baseline inline-cache messages\n"
" bl-ic-fb Baseline IC fallback stub messages\n"
" bl-osr Baseline IC OSR messages\n"
" bl-bails Baseline bailouts\n"
" bl-dbg-osr Baseline debug mode on stack recompile messages\n"
" bl-all All baseline spew\n"
"\n"
"See also SPEW=help for information on the Structured Spewer."
"\n");
exit(0);
/*NOTREACHED*/
}
if (ContainsFlag(env, "aborts")) {
EnableChannel(JitSpew_IonAbort);
}
if (ContainsFlag(env, "prune")) {
EnableChannel(JitSpew_Prune);
}
if (ContainsFlag(env, "escape")) {
EnableChannel(JitSpew_Escape);
}
if (ContainsFlag(env, "alias")) {
EnableChannel(JitSpew_Alias);
}
if (ContainsFlag(env, "alias-sum")) {
EnableChannel(JitSpew_AliasSummaries);
}
if (ContainsFlag(env, "scripts")) {
EnableChannel(JitSpew_IonScripts);
}
if (ContainsFlag(env, "mir")) {
EnableChannel(JitSpew_IonMIR);
}
if (ContainsFlag(env, "gvn")) {
EnableChannel(JitSpew_GVN);
}
if (ContainsFlag(env, "range")) {
EnableChannel(JitSpew_Range);
}
if (ContainsFlag(env, "licm")) {
EnableChannel(JitSpew_LICM);
}
if (ContainsFlag(env, "flac")) {
EnableChannel(JitSpew_FLAC);
}
if (ContainsFlag(env, "eaa")) {
EnableChannel(JitSpew_EAA);
}
if (ContainsFlag(env, "sincos")) {
EnableChannel(JitSpew_Sincos);
}
if (ContainsFlag(env, "sink")) {
EnableChannel(JitSpew_Sink);
}
if (ContainsFlag(env, "regalloc")) {
EnableChannel(JitSpew_RegAlloc);
}
if (ContainsFlag(env, "inline")) {
EnableChannel(JitSpew_Inlining);
}
if (ContainsFlag(env, "snapshots")) {
EnableChannel(JitSpew_IonSnapshots);
}
if (ContainsFlag(env, "codegen")) {
EnableChannel(JitSpew_Codegen);
}
if (ContainsFlag(env, "bailouts")) {
EnableChannel(JitSpew_IonBailouts);
}
if (ContainsFlag(env, "osi")) {
EnableChannel(JitSpew_IonInvalidate);
}
if (ContainsFlag(env, "caches")) {
EnableChannel(JitSpew_IonIC);
}
if (ContainsFlag(env, "safepoints")) {
EnableChannel(JitSpew_Safepoints);
}
if (ContainsFlag(env, "pools")) {
EnableChannel(JitSpew_Pools);
}
if (ContainsFlag(env, "cacheflush")) {
EnableChannel(JitSpew_CacheFlush);
}
if (ContainsFlag(env, "logs")) {
EnableIonDebugAsyncLogging();
}
if (ContainsFlag(env, "logs-sync")) {
EnableIonDebugSyncLogging();
}
if (ContainsFlag(env, "profiling")) {
EnableChannel(JitSpew_Profiling);
}
if (ContainsFlag(env, "trackopts")) {
JitOptions.disableOptimizationTracking = false;
EnableChannel(JitSpew_OptimizationTracking);
}
if (ContainsFlag(env, "trackopts-ext")) {
EnableChannel(JitSpew_OptimizationTrackingExtended);
}
if (ContainsFlag(env, "dump-mir-expr")) {
EnableChannel(JitSpew_MIRExpressions);
}
if (ContainsFlag(env, "cfg")) {
EnableChannel(JitSpew_CFG);
}
if (ContainsFlag(env, "all")) {
LoggingBits = uint64_t(-1);
}
if (ContainsFlag(env, "bl-aborts")) {
EnableChannel(JitSpew_BaselineAbort);
}
if (ContainsFlag(env, "bl-scripts")) {
EnableChannel(JitSpew_BaselineScripts);
}
if (ContainsFlag(env, "bl-op")) {
EnableChannel(JitSpew_BaselineOp);
}
if (ContainsFlag(env, "bl-ic")) {
EnableChannel(JitSpew_BaselineIC);
}
if (ContainsFlag(env, "bl-ic-fb")) {
EnableChannel(JitSpew_BaselineICFallback);
}
if (ContainsFlag(env, "bl-osr")) {
EnableChannel(JitSpew_BaselineOSR);
}
if (ContainsFlag(env, "bl-bails")) {
EnableChannel(JitSpew_BaselineBailouts);
}
if (ContainsFlag(env, "bl-dbg-osr")) {
EnableChannel(JitSpew_BaselineDebugModeOSR);
}
if (ContainsFlag(env, "bl-all")) {
EnableChannel(JitSpew_BaselineAbort);
EnableChannel(JitSpew_BaselineScripts);
EnableChannel(JitSpew_BaselineOp);
EnableChannel(JitSpew_BaselineIC);
EnableChannel(JitSpew_BaselineICFallback);
EnableChannel(JitSpew_BaselineOSR);
EnableChannel(JitSpew_BaselineBailouts);
EnableChannel(JitSpew_BaselineDebugModeOSR);
const char* found = strtok(env, ",");
while (found) {
fprintf(stderr, "found tag: %s\n", found);
// We're at the end of a flag; check if the previous substring was a
// known flag (i-1 is the last character of the flag we just read).
if (IsFlag(found, "help")) {
PrintHelpAndExit();
} else if (IsFlag(found, "aborts")) {
EnableChannel(JitSpew_IonAbort);
} else if (IsFlag(found, "prune")) {
EnableChannel(JitSpew_Prune);
} else if (IsFlag(found, "escape")) {
EnableChannel(JitSpew_Escape);
} else if (IsFlag(found, "alias")) {
EnableChannel(JitSpew_Alias);
} else if (IsFlag(found, "alias-sum")) {
EnableChannel(JitSpew_AliasSummaries);
} else if (IsFlag(found, "scripts")) {
EnableChannel(JitSpew_IonScripts);
} else if (IsFlag(found, "mir")) {
EnableChannel(JitSpew_IonMIR);
} else if (IsFlag(found, "gvn")) {
EnableChannel(JitSpew_GVN);
} else if (IsFlag(found, "range")) {
EnableChannel(JitSpew_Range);
} else if (IsFlag(found, "licm")) {
EnableChannel(JitSpew_LICM);
} else if (IsFlag(found, "flac")) {
EnableChannel(JitSpew_FLAC);
} else if (IsFlag(found, "eaa")) {
EnableChannel(JitSpew_EAA);
} else if (IsFlag(found, "sincos")) {
EnableChannel(JitSpew_Sincos);
} else if (IsFlag(found, "sink")) {
EnableChannel(JitSpew_Sink);
} else if (IsFlag(found, "regalloc")) {
EnableChannel(JitSpew_RegAlloc);
} else if (IsFlag(found, "inline")) {
EnableChannel(JitSpew_Inlining);
} else if (IsFlag(found, "snapshots")) {
EnableChannel(JitSpew_IonSnapshots);
} else if (IsFlag(found, "codegen")) {
EnableChannel(JitSpew_Codegen);
} else if (IsFlag(found, "bailouts")) {
EnableChannel(JitSpew_IonBailouts);
} else if (IsFlag(found, "osi")) {
EnableChannel(JitSpew_IonInvalidate);
} else if (IsFlag(found, "caches")) {
EnableChannel(JitSpew_IonIC);
} else if (IsFlag(found, "safepoints")) {
EnableChannel(JitSpew_Safepoints);
} else if (IsFlag(found, "pools")) {
EnableChannel(JitSpew_Pools);
} else if (IsFlag(found, "cacheflush")) {
EnableChannel(JitSpew_CacheFlush);
} else if (IsFlag(found, "logs")) {
EnableIonDebugAsyncLogging();
} else if (IsFlag(found, "logs-sync")) {
EnableIonDebugSyncLogging();
} else if (IsFlag(found, "profiling")) {
EnableChannel(JitSpew_Profiling);
} else if (IsFlag(found, "trackopts")) {
JitOptions.disableOptimizationTracking = false;
EnableChannel(JitSpew_OptimizationTracking);
} else if (IsFlag(found, "trackopts-ext")) {
EnableChannel(JitSpew_OptimizationTrackingExtended);
} else if (IsFlag(found, "dump-mir-expr")) {
EnableChannel(JitSpew_MIRExpressions);
} else if (IsFlag(found, "cfg")) {
EnableChannel(JitSpew_CFG);
} else if (IsFlag(found, "all")) {
LoggingBits = uint64_t(-1);
} else if (IsFlag(found, "bl-aborts")) {
EnableChannel(JitSpew_BaselineAbort);
} else if (IsFlag(found, "bl-scripts")) {
EnableChannel(JitSpew_BaselineScripts);
} else if (IsFlag(found, "bl-op")) {
EnableChannel(JitSpew_BaselineOp);
} else if (IsFlag(found, "bl-ic")) {
EnableChannel(JitSpew_BaselineIC);
} else if (IsFlag(found, "bl-ic-fb")) {
EnableChannel(JitSpew_BaselineICFallback);
} else if (IsFlag(found, "bl-osr")) {
EnableChannel(JitSpew_BaselineOSR);
} else if (IsFlag(found, "bl-bails")) {
EnableChannel(JitSpew_BaselineBailouts);
} else if (IsFlag(found, "bl-dbg-osr")) {
EnableChannel(JitSpew_BaselineDebugModeOSR);
} else if (IsFlag(found, "bl-all")) {
EnableChannel(JitSpew_BaselineAbort);
EnableChannel(JitSpew_BaselineScripts);
EnableChannel(JitSpew_BaselineOp);
EnableChannel(JitSpew_BaselineIC);
EnableChannel(JitSpew_BaselineICFallback);
EnableChannel(JitSpew_BaselineOSR);
EnableChannel(JitSpew_BaselineBailouts);
EnableChannel(JitSpew_BaselineDebugModeOSR);
} else {
fprintf(stderr, "Unknown flag.\n");
PrintHelpAndExit(64);
}
found = strtok(nullptr, ",");
}
FILE* spewfh = stderr;

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

@ -135,6 +135,7 @@ class GraphSpewer {
bool isSpewing() const { return graph_; }
void init(MIRGraph* graph, JSScript* function);
void beginFunction(JSScript* function);
void beginWasmFunction(unsigned funcIndex);
void spewPass(const char* pass);
void spewPass(const char* pass, BacktrackingAllocator* ra);
void endFunction();
@ -143,6 +144,8 @@ class GraphSpewer {
};
void SpewBeginFunction(MIRGenerator* mir, JSScript* function);
void SpewBeginWasmFunction(MIRGenerator* mir, unsigned funcIndex);
class AutoSpewEndFunction {
private:
MIRGenerator* mir_;
@ -202,6 +205,7 @@ class GraphSpewer {
};
static inline void SpewBeginFunction(MIRGenerator* mir, JSScript* function) {}
static inline void SpewBeginWasmFunction(MIRGenerator* mir, unsigned funcIndex) {}
class AutoSpewEndFunction {
public:

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

@ -202,6 +202,15 @@ void LIRGenerator::visitNewTypedArrayDynamicLength(
assignSafepoint(lir, ins);
}
void LIRGenerator::visitNewTypedArrayFromArray(MNewTypedArrayFromArray* ins) {
MDefinition* array = ins->array();
MOZ_ASSERT(array->type() == MIRType::Object);
auto* lir = new (alloc()) LNewTypedArrayFromArray(useRegisterAtStart(array));
defineReturn(lir, ins);
assignSafepoint(lir, ins);
}
void LIRGenerator::visitNewObject(MNewObject* ins) {
LNewObject* lir = new (alloc()) LNewObject(temp());
define(lir, ins);
@ -4132,6 +4141,10 @@ void LIRGenerator::visitIsTypedArray(MIsTypedArray* ins) {
auto* lir = new (alloc()) LIsTypedArray(useRegister(ins->value()));
define(lir, ins);
if (ins->isPossiblyWrapped()) {
assignSafepoint(lir, ins);
}
}
void LIRGenerator::visitIsCallable(MIsCallable* ins) {

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

@ -361,6 +361,8 @@ IonBuilder::InliningResult IonBuilder::inlineNativeCall(CallInfo& callInfo,
// TypedArray intrinsics.
case InlinableNative::TypedArrayConstructor:
return inlineTypedArray(callInfo, target->native());
case InlinableNative::IntrinsicIsTypedArrayConstructor:
return inlineIsTypedArrayConstructor(callInfo);
case InlinableNative::IntrinsicIsTypedArray:
return inlineIsTypedArray(callInfo);
case InlinableNative::IntrinsicIsPossiblyWrappedTypedArray:
@ -2929,19 +2931,11 @@ IonBuilder::InliningResult IonBuilder::inlineTypedArray(CallInfo& callInfo,
return InliningStatus_NotInlined;
}
MDefinition* arg = callInfo.getArg(0);
if (arg->type() != MIRType::Int32) {
return InliningStatus_NotInlined;
}
JSObject* templateObject = inspector->getTemplateObjectForNative(pc, native);
if (!templateObject) {
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeNoTemplateObj);
return InliningStatus_NotInlined;
}
MOZ_ASSERT(templateObject->is<TypedArrayObject>());
TypedArrayObject* obj = &templateObject->as<TypedArrayObject>();
@ -2951,41 +2945,96 @@ IonBuilder::InliningResult IonBuilder::inlineTypedArray(CallInfo& callInfo,
return InliningStatus_NotInlined;
}
MInstruction* ins = nullptr;
MDefinition* arg = callInfo.getArg(0);
MInstruction* ins;
if (arg->type() == MIRType::Int32) {
if (!arg->isConstant()) {
ins = MNewTypedArrayDynamicLength::New(
alloc(), constraints(), templateObject,
templateObject->group()->initialHeap(constraints()), arg);
} else {
// Negative lengths must throw a RangeError. (We don't track that this
// might have previously thrown, when determining whether to inline, so we
// have to deal with this error case when inlining.)
int32_t providedLen = arg->maybeConstantValue()->toInt32();
if (providedLen <= 0) {
return InliningStatus_NotInlined;
}
if (!arg->isConstant()) {
callInfo.setImplicitlyUsedUnchecked();
ins = MNewTypedArrayDynamicLength::New(
uint32_t len = AssertedCast<uint32_t>(providedLen);
if (obj->length() != len) {
return InliningStatus_NotInlined;
}
MConstant* templateConst =
MConstant::NewConstraintlessObject(alloc(), obj);
current->add(templateConst);
ins = MNewTypedArray::New(alloc(), constraints(), templateConst,
obj->group()->initialHeap(constraints()));
}
} else if (arg->type() == MIRType::Object) {
TemporaryTypeSet* types = arg->resultTypeSet();
if (!types) {
return InliningStatus_NotInlined;
}
// Don't inline if the argument is a, possibly wrapped, ArrayBuffer or
// SharedArrayBuffer object.
auto IsPossiblyWrappedArrayBufferMaybeSharedClass = [](const Class* clasp) {
return clasp->isProxy() || clasp == &ArrayBufferObject::class_ ||
clasp == &SharedArrayBufferObject::class_;
};
auto result = types->forAllClasses(
constraints(), IsPossiblyWrappedArrayBufferMaybeSharedClass);
if (result != TemporaryTypeSet::ForAllResult::ALL_FALSE) {
return InliningStatus_NotInlined;
}
ins = MNewTypedArrayFromArray::New(
alloc(), constraints(), templateObject,
templateObject->group()->initialHeap(constraints()), arg);
} else {
// Negative lengths must throw a RangeError. (We don't track that this
// might have previously thrown, when determining whether to inline, so we
// have to deal with this error case when inlining.)
int32_t providedLen = arg->maybeConstantValue()->toInt32();
if (providedLen <= 0) {
return InliningStatus_NotInlined;
}
uint32_t len = AssertedCast<uint32_t>(providedLen);
if (obj->length() != len) {
return InliningStatus_NotInlined;
}
callInfo.setImplicitlyUsedUnchecked();
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), obj);
current->add(templateConst);
ins = MNewTypedArray::New(alloc(), constraints(), templateConst,
obj->group()->initialHeap(constraints()));
return InliningStatus_NotInlined;
}
callInfo.setImplicitlyUsedUnchecked();
current->add(ins);
current->push(ins);
MOZ_TRY(resumeAfter(ins));
return InliningStatus_Inlined;
}
IonBuilder::InliningResult IonBuilder::inlineIsTypedArrayConstructor(
CallInfo& callInfo) {
MOZ_ASSERT(!callInfo.constructing());
MOZ_ASSERT(callInfo.argc() == 1);
if (getInlineReturnType() != MIRType::Boolean) {
return InliningStatus_NotInlined;
}
if (callInfo.getArg(0)->type() != MIRType::Object) {
return InliningStatus_NotInlined;
}
// Try inlining with a constant if the argument is definitely a TypedArray
// constructor.
TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
if (!types || types->unknownObject() || types->getObjectCount() == 0) {
return InliningStatus_NotInlined;
}
for (unsigned i = 0; i < types->getObjectCount(); i++) {
JSObject* singleton = types->getSingleton(i);
if (!singleton || !IsTypedArrayConstructor(singleton)) {
return InliningStatus_NotInlined;
}
}
callInfo.setImplicitlyUsedUnchecked();
pushConstant(BooleanValue(true));
return InliningStatus_Inlined;
}
IonBuilder::InliningResult IonBuilder::inlineIsTypedArrayHelper(
CallInfo& callInfo, WrappingBehavior wrappingBehavior) {
MOZ_ASSERT(!callInfo.constructing());
@ -3008,8 +3057,7 @@ IonBuilder::InliningResult IonBuilder::inlineIsTypedArrayHelper(
// Wrapped typed arrays won't appear to be typed arrays per a
// |forAllClasses| query. If wrapped typed arrays are to be considered
// typed arrays, a negative answer is not conclusive. Don't inline in
// that case.
// typed arrays, a negative answer is not conclusive.
auto isPossiblyWrapped = [this, wrappingBehavior, types]() {
if (wrappingBehavior != AllowWrappedTypedArrays) {
return false;
@ -3028,9 +3076,11 @@ IonBuilder::InliningResult IonBuilder::inlineIsTypedArrayHelper(
bool result = false;
bool isConstant = true;
bool possiblyWrapped = false;
switch (types->forAllClasses(constraints(), IsTypedArrayClass)) {
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
if (isPossiblyWrapped()) {
// Don't inline if we never saw typed arrays, but always only proxies.
return InliningStatus_NotInlined;
}
@ -3045,20 +3095,22 @@ IonBuilder::InliningResult IonBuilder::inlineIsTypedArrayHelper(
break;
case TemporaryTypeSet::ForAllResult::MIXED:
if (isPossiblyWrapped()) {
return InliningStatus_NotInlined;
}
isConstant = false;
possiblyWrapped = isPossiblyWrapped();
break;
}
if (isConstant) {
pushConstant(BooleanValue(result));
} else {
auto* ins = MIsTypedArray::New(alloc(), callInfo.getArg(0));
auto* ins =
MIsTypedArray::New(alloc(), callInfo.getArg(0), possiblyWrapped);
current->add(ins);
current->push(ins);
if (possiblyWrapped) {
MOZ_TRY(resumeAfter(ins));
}
}
callInfo.setImplicitlyUsedUnchecked();
@ -4052,6 +4104,8 @@ IonBuilder::InliningResult IonBuilder::inlineWasmCall(CallInfo& callInfo,
current->push(call);
current->add(call);
MOZ_TRY(resumeAfter(call));
callInfo.setImplicitlyUsedUnchecked();
return InliningStatus_Inlined;

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

@ -2138,12 +2138,10 @@ class MNewTypedArrayDynamicLength : public MUnaryInstruction,
: MUnaryInstruction(classOpcode, length),
templateObject_(templateObject),
initialHeap_(initialHeap) {
MOZ_ASSERT(!templateObject->isSingleton());
setGuard(); // Need to throw if length is negative.
setResultType(MIRType::Object);
if (!templateObject->isSingleton()) {
setResultTypeSet(
MakeSingletonTypeSet(alloc, constraints, templateObject));
}
setResultTypeSet(MakeSingletonTypeSet(alloc, constraints, templateObject));
}
public:
@ -2161,6 +2159,40 @@ class MNewTypedArrayDynamicLength : public MUnaryInstruction,
}
};
// Create a new TypedArray from an Array (or Array-like object) or a TypedArray.
class MNewTypedArrayFromArray : public MUnaryInstruction,
public SingleObjectPolicy::Data {
CompilerObject templateObject_;
gc::InitialHeap initialHeap_;
MNewTypedArrayFromArray(TempAllocator& alloc,
CompilerConstraintList* constraints,
JSObject* templateObject, gc::InitialHeap initialHeap,
MDefinition* array)
: MUnaryInstruction(classOpcode, array),
templateObject_(templateObject),
initialHeap_(initialHeap) {
MOZ_ASSERT(!templateObject->isSingleton());
setGuard(); // Can throw during construction.
setResultType(MIRType::Object);
setResultTypeSet(MakeSingletonTypeSet(alloc, constraints, templateObject));
}
public:
INSTRUCTION_HEADER(NewTypedArrayFromArray)
TRIVIAL_NEW_WRAPPERS_WITH_ALLOC
MDefinition* array() const { return getOperand(0); }
JSObject* templateObject() const { return templateObject_; }
gc::InitialHeap initialHeap() const { return initialHeap_; }
bool appendRoots(MRootList& roots) const override {
return roots.append(templateObject_);
}
bool possiblyCalls() const override { return true; }
};
class MNewObject : public MUnaryInstruction, public NoTypePolicy::Data {
public:
enum Mode { ObjectLiteral, ObjectCreate };
@ -10727,10 +10759,19 @@ class MIsArray : public MUnaryInstruction,
class MIsTypedArray : public MUnaryInstruction,
public SingleObjectPolicy::Data {
explicit MIsTypedArray(MDefinition* value)
: MUnaryInstruction(classOpcode, value) {
bool possiblyWrapped_;
explicit MIsTypedArray(MDefinition* value, bool possiblyWrapped)
: MUnaryInstruction(classOpcode, value),
possiblyWrapped_(possiblyWrapped) {
setResultType(MIRType::Boolean);
setMovable();
if (possiblyWrapped) {
// Proxy checks may throw, so we're neither removable nor movable.
setGuard();
} else {
setMovable();
}
}
public:
@ -10738,6 +10779,7 @@ class MIsTypedArray : public MUnaryInstruction,
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, value))
bool isPossiblyWrapped() const { return possiblyWrapped_; }
AliasSet getAliasSet() const override { return AliasSet::None(); }
};

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

@ -1797,6 +1797,17 @@ MOZ_MUST_USE bool TrySkipAwait(JSContext* cx, HandleValue val,
return true;
}
bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result) {
JSObject* unwrapped = CheckedUnwrap(obj);
if (!unwrapped) {
ReportAccessDenied(cx);
return false;
}
*result = unwrapped->is<TypedArrayObject>();
return true;
}
typedef bool (*ProxyGetPropertyFn)(JSContext*, HandleObject, HandleId,
MutableHandleValue);
const VMFunction ProxyGetPropertyInfo =

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

@ -1182,6 +1182,8 @@ bool DoConcatStringObject(JSContext* cx, HandleValue lhs, HandleValue rhs,
MOZ_MUST_USE bool TrySkipAwait(JSContext* cx, HandleValue val,
MutableHandleValue resolved);
bool IsPossiblyWrappedTypedArray(JSContext* cx, JSObject* obj, bool* result);
// VMFunctions shared by JITs
extern const VMFunction SetArrayLengthInfo;
extern const VMFunction SetObjectElementInfo;

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

@ -48,7 +48,7 @@ class LBinaryMath : public LInstructionHelper<1, 2 + ExtraUses, Temps> {
//
// Note: LSafepoints are 1:1 with LOsiPoints, so it holds a reference to the
// corresponding LSafepoint to inform it of the LOsiPoint's masm offset when it
// gets CG'd.
// gets GC'd.
class LOsiPoint : public LInstructionHelper<0, 0, 0> {
LSafepoint* safepoint_;
@ -386,6 +386,22 @@ class LNewTypedArrayDynamicLength : public LInstructionHelper<1, 1, 1> {
}
};
class LNewTypedArrayFromArray : public LCallInstructionHelper<1, 1, 0> {
public:
LIR_HEADER(NewTypedArrayFromArray)
explicit LNewTypedArrayFromArray(const LAllocation& array)
: LCallInstructionHelper(classOpcode) {
setOperand(0, array);
}
const LAllocation* array() { return getOperand(0); }
MNewTypedArrayFromArray* mir() const {
return mir_->toNewTypedArrayFromArray();
}
};
class LNewObject : public LInstructionHelper<1, 0, 1> {
public:
LIR_HEADER(NewObject)
@ -6070,6 +6086,7 @@ class LIsTypedArray : public LInstructionHelper<1, 1, 0> {
setOperand(0, object);
}
const LAllocation* object() { return getOperand(0); }
MIsTypedArray* mir() const { return mir_->toIsTypedArray(); }
};
class LIsObject : public LInstructionHelper<1, BOX_PIECES, 0> {

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

@ -872,7 +872,7 @@ JS_PUBLIC_API bool JS_ResolveStandardClass(JSContext* cx, HandleObject obj,
JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
if (key != JSProto_Null) {
const Class* clasp = ProtoKeyToClass(key);
if (!clasp || !(clasp->flags & JSCLASS_IS_ANONYMOUS)) {
if (!clasp || clasp->specShouldDefineConstructor()) {
if (!GlobalObject::ensureConstructor(cx, global, key)) {
return false;
}
@ -947,9 +947,6 @@ static bool EnumerateStandardClassesInTable(JSContext* cx,
}
if (const Class* clasp = ProtoKeyToClass(key)) {
if (clasp->flags & JSCLASS_IS_ANONYMOUS) {
continue;
}
if (!clasp->specShouldDefineConstructor()) {
continue;
}

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

@ -1260,3 +1260,7 @@ skip script test262/harness/detachArrayBuffer.js
# https://github.com/tc39/test262/pull/1965
skip script test262/language/expressions/dynamic-import/indirect-resolution.js
skip script test262/language/expressions/dynamic-import/namespace/default-property-not-set-own.js
# https://github.com/tc39/test262/pull/2023
skip script test262/language/statements/try/early-catch-var.js
skip script test262/language/eval-code/direct/var-env-lower-lex-catch-non-strict.js

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

@ -1,12 +1,12 @@
// |reftest| skip-if(!xulRuntime.shell)
assertThrowsInstanceOf(() => evaluate(`
evaluate(`
try { throw null; } catch (e) { eval("for (var e of []) {}") }
`), SyntaxError);
`);
assertThrowsInstanceOf(new Function(`
new Function(`
try { throw null; } catch (e) { eval("for (var e of []) {}") }
`), SyntaxError);
`)();
if (typeof reportCompare === "function")
reportCompare(true, true);

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

@ -82,6 +82,14 @@ function h1() {
}
h1();
// Tests that var declaration is allowed in for-of head.
function h2() {
try {} catch (e) {
for (var e of {});
}
}
h2();
// Tests that redeclaring a var inside the catch is allowed.
function h3() {
var e;
@ -91,16 +99,6 @@ function h3() {
}
h3();
// Tests that var declaration is not allowed in for-of head.
assertThrowsInstanceOf(function () {
eval(`
function h2() {
try {} catch (e) { for (var e of {}); }
}
log += 'unreached';
`);
}, SyntaxError);
if (typeof evaluate === "function") {
assertThrowsInstanceOf(function () {
evaluate(`

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

@ -222,8 +222,7 @@ CallObject* CallObject::createHollowForDebug(JSContext* cx,
}
const Class CallObject::class_ = {
"Call", JSCLASS_IS_ANONYMOUS |
JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS)};
"Call", JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS)};
/*****************************************************************************/
@ -318,8 +317,7 @@ const Class CallObject::class_ = {
}
const Class VarEnvironmentObject::class_ = {
"Var", JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(
VarEnvironmentObject::RESERVED_SLOTS)};
"Var", JSCLASS_HAS_RESERVED_SLOTS(VarEnvironmentObject::RESERVED_SLOTS)};
/*****************************************************************************/
@ -342,8 +340,7 @@ const ClassOps ModuleEnvironmentObject::classOps_ = {
const Class ModuleEnvironmentObject::class_ = {
"ModuleEnvironmentObject",
JSCLASS_HAS_RESERVED_SLOTS(ModuleEnvironmentObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JSCLASS_HAS_RESERVED_SLOTS(ModuleEnvironmentObject::RESERVED_SLOTS),
&ModuleEnvironmentObject::classOps_,
JS_NULL_CLASS_SPEC,
JS_NULL_CLASS_EXT,
@ -554,8 +551,7 @@ void ModuleEnvironmentObject::fixEnclosingEnvironmentAfterCompartmentMerge(
const Class WasmInstanceEnvironmentObject::class_ = {
"WasmInstance",
JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(
WasmInstanceEnvironmentObject::RESERVED_SLOTS)};
JSCLASS_HAS_RESERVED_SLOTS(WasmInstanceEnvironmentObject::RESERVED_SLOTS)};
/* static */ WasmInstanceEnvironmentObject*
WasmInstanceEnvironmentObject::createHollowForDebug(
@ -591,8 +587,7 @@ WasmInstanceEnvironmentObject::createHollowForDebug(
const Class WasmFunctionCallObject::class_ = {
"WasmCall",
JSCLASS_IS_ANONYMOUS |
JSCLASS_HAS_RESERVED_SLOTS(WasmFunctionCallObject::RESERVED_SLOTS)};
JSCLASS_HAS_RESERVED_SLOTS(WasmFunctionCallObject::RESERVED_SLOTS)};
/* static */ WasmFunctionCallObject*
WasmFunctionCallObject::createHollowForDebug(JSContext* cx,
@ -791,8 +786,7 @@ static const ObjectOps WithEnvironmentObjectOps = {
const Class WithEnvironmentObject::class_ = {
"With",
JSCLASS_HAS_RESERVED_SLOTS(WithEnvironmentObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JSCLASS_HAS_RESERVED_SLOTS(WithEnvironmentObject::RESERVED_SLOTS),
JS_NULL_CLASS_OPS,
JS_NULL_CLASS_SPEC,
JS_NULL_CLASS_EXT,
@ -818,8 +812,7 @@ const Class WithEnvironmentObject::class_ = {
const Class NonSyntacticVariablesObject::class_ = {
"NonSyntacticVariablesObject",
JSCLASS_HAS_RESERVED_SLOTS(NonSyntacticVariablesObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS};
JSCLASS_HAS_RESERVED_SLOTS(NonSyntacticVariablesObject::RESERVED_SLOTS)};
bool js::CreateNonSyntacticEnvironmentChain(JSContext* cx,
AutoObjectVector& envChain,
@ -1069,8 +1062,7 @@ void LexicalEnvironmentObject::setWindowProxyThisValue(JSObject* obj) {
const Class LexicalEnvironmentObject::class_ = {
"LexicalEnvironment",
JSCLASS_HAS_RESERVED_SLOTS(LexicalEnvironmentObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JSCLASS_HAS_RESERVED_SLOTS(LexicalEnvironmentObject::RESERVED_SLOTS),
JS_NULL_CLASS_OPS,
JS_NULL_CLASS_SPEC,
JS_NULL_CLASS_EXT,
@ -1211,8 +1203,7 @@ static const ObjectOps RuntimeLexicalErrorObjectObjectOps = {
const Class RuntimeLexicalErrorObject::class_ = {
"RuntimeLexicalError",
JSCLASS_HAS_RESERVED_SLOTS(RuntimeLexicalErrorObject::RESERVED_SLOTS) |
JSCLASS_IS_ANONYMOUS,
JSCLASS_HAS_RESERVED_SLOTS(RuntimeLexicalErrorObject::RESERVED_SLOTS),
JS_NULL_CLASS_OPS,
JS_NULL_CLASS_SPEC,
JS_NULL_CLASS_EXT,

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

@ -348,8 +348,7 @@ TypedObjectModuleObject& js::GlobalObject::getTypedObjectModule() const {
}
const Class GlobalObject::OffThreadPlaceholderObject::class_ = {
"off-thread-prototype-placeholder",
JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_RESERVED_SLOTS(1)};
"off-thread-prototype-placeholder", JSCLASS_HAS_RESERVED_SLOTS(1)};
/* static */ GlobalObject::OffThreadPlaceholderObject*
GlobalObject::OffThreadPlaceholderObject::New(JSContext* cx, unsigned slot) {

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

@ -2011,15 +2011,8 @@ static NativeObject* DefineConstructorAndPrototype(
return nullptr;
}
// Attributes used when installing the constructor on |obj|.
uint32_t propertyAttrs = 0;
RootedNativeObject ctor(cx);
if (!constructor) {
if (clasp->flags & JSCLASS_IS_ANONYMOUS) {
propertyAttrs = JSPROP_READONLY | JSPROP_PERMANENT;
}
ctor = proto;
} else {
ctor = NewNativeConstructor(cx, constructor, nargs, atom);
@ -2040,7 +2033,7 @@ static NativeObject* DefineConstructorAndPrototype(
RootedId id(cx, AtomToId(atom));
RootedValue value(cx, ObjectValue(*ctor));
if (!DefineDataProperty(cx, obj, id, value, propertyAttrs)) {
if (!DefineDataProperty(cx, obj, id, value, 0)) {
return nullptr;
}

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

@ -1346,8 +1346,7 @@ static const ClassOps ScriptSourceObjectClassOps = {
const Class ScriptSourceObject::class_ = {
"ScriptSource",
JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_IS_ANONYMOUS |
JSCLASS_FOREGROUND_FINALIZE,
JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS) | JSCLASS_FOREGROUND_FINALIZE,
&ScriptSourceObjectClassOps};
ScriptSourceObject* ScriptSourceObject::createInternal(JSContext* cx,

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

@ -159,6 +159,39 @@ bool js::ForOfPIC::Chain::tryOptimizeArray(JSContext* cx,
return true;
}
bool js::ForOfPIC::Chain::tryOptimizeArrayIteratorNext(JSContext* cx,
bool* optimized) {
MOZ_ASSERT(optimized);
*optimized = false;
if (!initialized_) {
// If PIC is not initialized, initialize it.
if (!initialize(cx)) {
return false;
}
} else if (!disabled_ && !isArrayNextStillSane()) {
// Otherwise, if array iterator state is no longer sane, reinitialize.
reset();
if (!initialize(cx)) {
return false;
}
}
MOZ_ASSERT(initialized_);
// If PIC is disabled, don't bother trying to optimize.
if (disabled_) {
return true;
}
// By the time we get here, we should have a sane iterator state to work with.
MOZ_ASSERT(isArrayNextStillSane());
*optimized = true;
return true;
}
bool js::ForOfPIC::Chain::hasMatchingStub(ArrayObject* obj) {
// Ensure PIC is initialized and not disabled.
MOZ_ASSERT(initialized_ && !disabled_);
@ -291,8 +324,8 @@ const Class ForOfPIC::class_ = {
/* static */ NativeObject* js::ForOfPIC::createForOfPICObject(
JSContext* cx, Handle<GlobalObject*> global) {
cx->check(global);
NativeObject* obj =
NewNativeObjectWithGivenProto(cx, &ForOfPIC::class_, nullptr);
NativeObject* obj = NewNativeObjectWithGivenProto(cx, &ForOfPIC::class_,
nullptr, TenuredObject);
if (!obj) {
return nullptr;
}

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

@ -203,6 +203,13 @@ struct ForOfPIC {
bool tryOptimizeArray(JSContext* cx, HandleArrayObject array,
bool* optimized);
// Check if %ArrayIteratorPrototype% still uses the default "next" method.
bool tryOptimizeArrayIteratorNext(JSContext* cx, bool* optimized);
void trace(JSTracer* trc);
void sweep(FreeOp* fop);
private:
// Check if the global array-related objects have not been messed with
// in a way that would disable this PIC.
bool isArrayStateStillSane();
@ -215,10 +222,6 @@ struct ForOfPIC {
canonicalNextFunc_);
}
void trace(JSTracer* trc);
void sweep(FreeOp* fop);
private:
// Check if a matching optimized stub for the given object exists.
bool hasMatchingStub(ArrayObject* obj);

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

@ -352,7 +352,7 @@ const ClassSpec SavedFrame::classSpec_ = {
/* static */ const Class SavedFrame::class_ = {
"SavedFrame",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SavedFrame::JSSLOT_COUNT) |
JSCLASS_HAS_CACHED_PROTO(JSProto_SavedFrame) | JSCLASS_IS_ANONYMOUS |
JSCLASS_HAS_CACHED_PROTO(JSProto_SavedFrame) |
JSCLASS_FOREGROUND_FINALIZE,
&SavedFrameClassOps, &SavedFrame::classSpec_};

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

@ -50,6 +50,7 @@
#include "vm/JSContext.h"
#include "vm/JSFunction.h"
#include "vm/JSObject.h"
#include "vm/PIC.h"
#include "vm/Printer.h"
#include "vm/Realm.h"
#include "vm/RegExpObject.h"
@ -67,6 +68,7 @@
#include "vm/NativeObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/StringObject-inl.h"
#include "vm/TypedArrayObject-inl.h"
using namespace js;
using namespace js::selfhosted;
@ -796,6 +798,25 @@ bool js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool intrinsic_ArrayIteratorPrototypeOptimizable(JSContext* cx,
unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
if (!stubChain) {
return false;
}
bool optimized;
if (!stubChain->tryOptimizeArrayIteratorNext(cx, &optimized)) {
return false;
}
args.rval().setBoolean(optimized);
return true;
}
static bool intrinsic_GetNextMapEntryForIterator(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@ -1068,6 +1089,16 @@ static bool intrinsic_GetTypedArrayKind(JSContext* cx, unsigned argc,
return true;
}
static bool intrinsic_IsTypedArrayConstructor(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isObject());
args.rval().setBoolean(js::IsTypedArrayConstructor(&args[0].toObject()));
return true;
}
static bool intrinsic_TypedArrayBuffer(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@ -1705,6 +1736,43 @@ static bool intrinsic_TypedArrayBitwiseSlice(JSContext* cx, unsigned argc,
return true;
}
static bool intrinsic_TypedArrayInitFromPackedArray(JSContext* cx,
unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[1].isObject());
Rooted<TypedArrayObject*> target(cx,
&args[0].toObject().as<TypedArrayObject>());
MOZ_ASSERT(!target->hasDetachedBuffer());
MOZ_ASSERT(!target->isSharedMemory());
RootedArrayObject source(cx, &args[1].toObject().as<ArrayObject>());
MOZ_ASSERT(IsPackedArray(source));
MOZ_ASSERT(source->length() == target->length());
switch (target->type()) {
#define INIT_TYPED_ARRAY(T, N) \
case Scalar::N: { \
if (!ElementSpecific<T, UnsharedOps>::initFromIterablePackedArray( \
cx, target, source)) { \
return false; \
} \
break; \
}
JS_FOR_EACH_TYPED_ARRAY(INIT_TYPED_ARRAY)
#undef INIT_TYPED_ARRAY
default:
MOZ_CRASH(
"TypedArrayInitFromPackedArray with a typed array with bogus type");
}
args.rval().setUndefined();
return true;
}
static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@ -2121,24 +2189,6 @@ static bool intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc,
return true;
}
static bool intrinsic_NameForTypedArray(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isObject());
auto* object = UnwrapAndDowncastValue<TypedArrayObject>(cx, args[0]);
if (!object) {
return false;
}
JSProtoKey protoKey = StandardProtoKeyOrNull(object);
MOZ_ASSERT(protoKey);
args.rval().setString(ClassName(protoKey, cx));
return true;
}
static bool intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
@ -2428,7 +2478,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("MakeDefaultConstructor", intrinsic_MakeDefaultConstructor, 2, 0),
JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,
0),
JS_FN("_NameForTypedArray", intrinsic_NameForTypedArray, 1, 0),
JS_FN("DecompileArg", intrinsic_DecompileArg, 2, 0),
JS_INLINABLE_FN("_FinishBoundFunctionInit",
intrinsic_FinishBoundFunctionInit, 3, 0,
@ -2469,6 +2518,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0, 0,
IntrinsicNewArrayIterator),
JS_FN("ArrayIteratorPrototypeOptimizable",
intrinsic_ArrayIteratorPrototypeOptimizable, 0, 0),
JS_FN("CallArrayIteratorMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>, 2, 0),
@ -2566,6 +2617,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
"IsPossiblyWrappedTypedArray",
intrinsic_IsPossiblyWrappedInstanceOfBuiltin<TypedArrayObject>, 1, 0,
IntrinsicIsPossiblyWrappedTypedArray),
JS_INLINABLE_FN("IsTypedArrayConstructor",
intrinsic_IsTypedArrayConstructor, 1, 0,
IntrinsicIsTypedArrayConstructor),
JS_FN("TypedArrayBuffer", intrinsic_TypedArrayBuffer, 1, 0),
JS_FN("TypedArrayByteOffset", intrinsic_TypedArrayByteOffset, 1, 0),
@ -2591,6 +2645,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("TypedArrayBitwiseSlice", intrinsic_TypedArrayBitwiseSlice, 4, 0),
JS_FN("TypedArrayInitFromPackedArray",
intrinsic_TypedArrayInitFromPackedArray, 2, 0),
JS_FN("CallArrayBufferMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<ArrayBufferObject>>, 2, 0),
JS_FN("CallSharedArrayBufferMethodIfWrapped",

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

@ -382,11 +382,26 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
static TypedArrayObject* makeTypedInstance(JSContext* cx,
CreateSingleton createSingleton,
HandleObjectGroup group,
gc::AllocKind allocKind) {
if (createSingleton == CreateSingleton::Yes) {
MOZ_ASSERT(!group);
return newBuiltinClassInstance(cx, allocKind, SingletonObject);
}
if (group) {
MOZ_ASSERT(group->clasp() == instanceClass());
NewObjectKind newKind = GenericObject;
{
AutoSweepObjectGroup sweep(group);
if (group->shouldPreTenure(sweep)) {
newKind = TenuredObject;
}
}
return NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind,
newKind);
}
jsbytecode* pc;
RootedScript script(cx, cx->currentScript(&pc));
Rooted<TypedArrayObject*> obj(
@ -406,7 +421,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
static TypedArrayObject* makeInstance(
JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> buffer,
CreateSingleton createSingleton, uint32_t byteOffset, uint32_t len,
HandleObject proto) {
HandleObject proto, HandleObjectGroup group = nullptr) {
MOZ_ASSERT(len < INT32_MAX / BYTES_PER_ELEMENT);
gc::AllocKind allocKind =
@ -427,9 +442,10 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
AutoSetNewObjectMetadata metadata(cx);
Rooted<TypedArrayObject*> obj(cx);
if (proto && proto != checkProto) {
MOZ_ASSERT(!group);
obj = makeProtoInstance(cx, proto, allocKind);
} else {
obj = makeTypedInstance(cx, createSingleton, allocKind);
obj = makeTypedInstance(cx, createSingleton, group, allocKind);
}
if (!obj || !obj->init(cx, buffer, byteOffset, len, BYTES_PER_ELEMENT)) {
return nullptr;
@ -446,6 +462,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
bool fitsInline = nbytes <= INLINE_BUFFER_LIMIT;
gc::AllocKind allocKind = !fitsInline ? gc::GetGCObjectKind(instanceClass())
: AllocKindForLazyBuffer(nbytes);
MOZ_ASSERT(allocKind >= gc::GetGCObjectKind(instanceClass()));
AutoSetNewObjectMetadata metadata(cx);
jsbytecode* pc;
@ -552,6 +569,15 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
return obj;
}
static TypedArrayObject* makeTypedArrayWithTemplate(
JSContext* cx, TypedArrayObject* templateObj, HandleObject array) {
MOZ_ASSERT(!IsWrapper(array));
MOZ_ASSERT(!array->is<ArrayBufferObjectMaybeShared>());
RootedObjectGroup group(cx, templateObj->group());
return fromArray(cx, array, nullptr, group);
}
// ES2018 draft rev 8340bf9a8427ea81bb0d1459471afbcc91d18add
// 22.2.4.1 TypedArray ( )
// 22.2.4.2 TypedArray ( length )
@ -881,14 +907,17 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
uint32_t count,
MutableHandle<ArrayBufferObject*> buffer);
static JSObject* fromArray(JSContext* cx, HandleObject other,
HandleObject proto = nullptr);
static TypedArrayObject* fromArray(JSContext* cx, HandleObject other,
HandleObject proto = nullptr,
HandleObjectGroup group = nullptr);
static JSObject* fromTypedArray(JSContext* cx, HandleObject other,
bool isWrapped, HandleObject proto);
static TypedArrayObject* fromTypedArray(JSContext* cx, HandleObject other,
bool isWrapped, HandleObject proto,
HandleObjectGroup group);
static JSObject* fromObject(JSContext* cx, HandleObject other,
HandleObject proto);
static TypedArrayObject* fromObject(JSContext* cx, HandleObject other,
HandleObject proto,
HandleObjectGroup group);
static const NativeType getIndex(TypedArrayObject* tarray, uint32_t index) {
MOZ_ASSERT(index < tarray->length());
@ -931,6 +960,24 @@ TypedArrayObject* js::TypedArrayCreateWithTemplate(JSContext* cx,
}
}
TypedArrayObject* js::TypedArrayCreateWithTemplate(JSContext* cx,
HandleObject templateObj,
HandleObject array) {
MOZ_ASSERT(templateObj->is<TypedArrayObject>());
TypedArrayObject* tobj = &templateObj->as<TypedArrayObject>();
switch (tobj->type()) {
#define CREATE_TYPED_ARRAY(T, N) \
case Scalar::N: \
return TypedArrayObjectTemplate<T>::makeTypedArrayWithTemplate(cx, tobj, \
array);
JS_FOR_EACH_TYPED_ARRAY(CREATE_TYPED_ARRAY)
#undef CREATE_TYPED_ARRAY
default:
MOZ_CRASH("Unsupported TypedArray type");
}
}
// ES2018 draft rev 2aea8f3e617b49df06414eb062ab44fad87661d3
// 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength )
// byteLength = count * BYTES_PER_ELEMENT
@ -1025,27 +1072,29 @@ static JSObject* GetBufferSpeciesConstructor(
}
template <typename T>
/* static */ JSObject* TypedArrayObjectTemplate<T>::fromArray(
JSContext* cx, HandleObject other, HandleObject proto /* = nullptr */) {
/* static */ TypedArrayObject* TypedArrayObjectTemplate<T>::fromArray(
JSContext* cx, HandleObject other, HandleObject proto /* = nullptr */,
HandleObjectGroup group /* = nullptr */) {
// Allow nullptr proto for FriendAPI methods, which don't care about
// subclassing.
if (other->is<TypedArrayObject>()) {
return fromTypedArray(cx, other, /* wrapped= */ false, proto);
return fromTypedArray(cx, other, /* wrapped= */ false, proto, group);
}
if (other->is<WrapperObject>() &&
UncheckedUnwrap(other)->is<TypedArrayObject>()) {
return fromTypedArray(cx, other, /* wrapped= */ true, proto);
return fromTypedArray(cx, other, /* wrapped= */ true, proto, group);
}
return fromObject(cx, other, proto);
return fromObject(cx, other, proto, group);
}
// ES2018 draft rev 272beb67bc5cd9fd18a220665198384108208ee1
// 22.2.4.3 TypedArray ( typedArray )
template <typename T>
/* static */ JSObject* TypedArrayObjectTemplate<T>::fromTypedArray(
JSContext* cx, HandleObject other, bool isWrapped, HandleObject proto) {
/* static */ TypedArrayObject* TypedArrayObjectTemplate<T>::fromTypedArray(
JSContext* cx, HandleObject other, bool isWrapped, HandleObject proto,
HandleObjectGroup group) {
// Step 1.
MOZ_ASSERT_IF(!isWrapped, other->is<TypedArrayObject>());
MOZ_ASSERT_IF(isWrapped, other->is<WrapperObject>() &&
@ -1123,8 +1172,8 @@ template <typename T>
// Steps 3-4 (remaining part), 20-23.
Rooted<TypedArrayObject*> obj(
cx,
makeInstance(cx, buffer, CreateSingleton::No, 0, elementLength, proto));
cx, makeInstance(cx, buffer, CreateSingleton::No, 0, elementLength, proto,
group));
if (!obj) {
return nullptr;
}
@ -1165,8 +1214,9 @@ static MOZ_ALWAYS_INLINE bool IsOptimizableInit(JSContext* cx,
// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
// 22.2.4.4 TypedArray ( object )
template <typename T>
/* static */ JSObject* TypedArrayObjectTemplate<T>::fromObject(
JSContext* cx, HandleObject other, HandleObject proto) {
/* static */ TypedArrayObject* TypedArrayObjectTemplate<T>::fromObject(
JSContext* cx, HandleObject other, HandleObject proto,
HandleObjectGroup group) {
// Steps 1-2 (Already performed in caller).
// Steps 3-4 (Allocation deferred until later).
@ -1191,7 +1241,8 @@ template <typename T>
}
Rooted<TypedArrayObject*> obj(
cx, makeInstance(cx, buffer, CreateSingleton::No, 0, len, proto));
cx,
makeInstance(cx, buffer, CreateSingleton::No, 0, len, proto, group));
if (!obj) {
return nullptr;
}
@ -1266,7 +1317,7 @@ template <typename T>
}
Rooted<TypedArrayObject*> obj(
cx, makeInstance(cx, buffer, CreateSingleton::No, 0, len, proto));
cx, makeInstance(cx, buffer, CreateSingleton::No, 0, len, proto, group));
if (!obj) {
return nullptr;
}
@ -1290,17 +1341,46 @@ bool TypedArrayConstructor(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
template <typename T>
static bool GetTemplateObjectForNative(JSContext* cx, HandleValue arg,
MutableHandleObject res) {
if (arg.isInt32()) {
uint32_t len = 0;
if (arg.toInt32() >= 0) {
len = arg.toInt32();
}
size_t nbytes;
if (!js::CalculateAllocSize<T>(len, &nbytes)) {
return true;
}
if (nbytes >= TypedArrayObject::SINGLETON_BYTE_LENGTH) {
return true;
}
res.set(TypedArrayObjectTemplate<T>::makeTemplateObject(cx, len));
return !!res;
}
if (arg.isObject() && !IsWrapper(&arg.toObject()) &&
!arg.toObject().is<ArrayBufferObjectMaybeShared>()) {
// We don't use the template's length in the object case, so we can create
// the template typed array with an initial length of zero.
uint32_t len = 0;
res.set(TypedArrayObjectTemplate<T>::makeTemplateObject(cx, len));
return !!res;
}
return true;
}
/* static */ bool TypedArrayObject::GetTemplateObjectForNative(
JSContext* cx, Native native, uint32_t len, MutableHandleObject res) {
#define CHECK_TYPED_ARRAY_CONSTRUCTOR(T, N) \
if (native == &TypedArrayObjectTemplate<T>::class_constructor) { \
size_t nbytes; \
if (!js::CalculateAllocSize<T>(len, &nbytes)) return true; \
\
if (nbytes < TypedArrayObject::SINGLETON_BYTE_LENGTH) { \
res.set(TypedArrayObjectTemplate<T>::makeTemplateObject(cx, len)); \
return !!res; \
} \
JSContext* cx, Native native, HandleValue arg, MutableHandleObject res) {
MOZ_ASSERT(!res);
#define CHECK_TYPED_ARRAY_CONSTRUCTOR(T, N) \
if (native == &TypedArrayObjectTemplate<T>::class_constructor) { \
return ::GetTemplateObjectForNative<T>(cx, arg, res); \
}
JS_FOR_EACH_TYPED_ARRAY(CHECK_TYPED_ARRAY_CONSTRUCTOR)
#undef CHECK_TYPED_ARRAY_CONSTRUCTOR
@ -1328,6 +1408,38 @@ bool BufferGetterImpl(JSContext* cx, const CallArgs& args) {
return CallNonGenericMethod<TypedArrayObject::is, BufferGetterImpl>(cx, args);
}
// ES2019 draft rev fc9ecdcd74294d0ca3146d4b274e2a8e79565dc3
// 22.2.3.32 get %TypedArray%.prototype [ @@toStringTag ]
static bool TypedArray_toStringTagGetter(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
// Steps 1-2.
if (!args.thisv().isObject()) {
args.rval().setUndefined();
return true;
}
JSObject* obj = CheckedUnwrap(&args.thisv().toObject());
if (!obj) {
ReportAccessDenied(cx);
return false;
}
// Step 3.
if (!obj->is<TypedArrayObject>()) {
args.rval().setUndefined();
return true;
}
// Steps 4-6.
JSProtoKey protoKey = StandardProtoKeyOrNull(obj);
MOZ_ASSERT(protoKey);
args.rval().setString(ClassName(protoKey, cx));
return true;
}
/* static */ const JSPropertySpec TypedArrayObject::protoAccessors[] = {
JS_PSG("length", TypedArray_lengthGetter, 0),
JS_PSG("buffer", TypedArray_bufferGetter, 0),
@ -1335,7 +1447,7 @@ bool BufferGetterImpl(JSContext* cx, const CallArgs& args) {
TypedArrayObject::Getter<TypedArrayObject::byteLengthValue>, 0),
JS_PSG("byteOffset",
TypedArrayObject::Getter<TypedArrayObject::byteOffsetValue>, 0),
JS_SELF_HOSTED_SYM_GET(toStringTag, "TypedArrayToStringTag", 0),
JS_SYM_GET(toStringTag, TypedArray_toStringTagGetter, 0),
JS_PS_END};
template <typename T>
@ -1858,6 +1970,16 @@ const Class TypedArrayObject::protoClasses[Scalar::MaxTypedArrayViewType] = {
return native == TypedArray_lengthGetter;
}
bool js::IsTypedArrayConstructor(const JSObject* obj) {
#define CHECK_TYPED_ARRAY_CONSTRUCTOR(T, N) \
if (IsNativeFunction(obj, N##Array::class_constructor)) { \
return true; \
}
JS_FOR_EACH_TYPED_ARRAY(CHECK_TYPED_ARRAY_CONSTRUCTOR)
#undef CHECK_TYPED_ARRAY_CONSTRUCTOR
return false;
}
bool js::IsTypedArrayConstructor(HandleValue v, uint32_t type) {
switch (type) {
case Scalar::Int8:

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

@ -136,7 +136,8 @@ class TypedArrayObject : public ArrayBufferViewObject {
void getElements(Value* vp);
static bool GetTemplateObjectForNative(JSContext* cx, Native native,
uint32_t len, MutableHandleObject res);
HandleValue arg,
MutableHandleObject res);
/*
* Byte length above which created typed arrays will have singleton types
@ -191,6 +192,10 @@ extern TypedArrayObject* TypedArrayCreateWithTemplate(JSContext* cx,
HandleObject templateObj,
int32_t len);
extern TypedArrayObject* TypedArrayCreateWithTemplate(JSContext* cx,
HandleObject templateObj,
HandleObject array);
inline bool IsTypedArrayClass(const Class* clasp) {
return &TypedArrayObject::classes[0] <= clasp &&
clasp < &TypedArrayObject::classes[Scalar::MaxTypedArrayViewType];
@ -201,6 +206,8 @@ inline Scalar::Type GetTypedArrayClassType(const Class* clasp) {
return static_cast<Scalar::Type>(clasp - &TypedArrayObject::classes[0]);
}
bool IsTypedArrayConstructor(const JSObject* obj);
bool IsTypedArrayConstructor(HandleValue v, uint32_t type);
// In WebIDL terminology, a BufferSource is either an ArrayBuffer or a typed

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

@ -177,7 +177,7 @@ void WasmFrameIter::popFrame() {
// | WASM FRAME | (already unwound)
// |---------------------|
//
// The next value of FP is just a regular jit frame used marked to
// The next value of FP is just a regular jit frame used as a marker to
// know that we should transition to a JSJit frame iterator.
unwoundIonCallerFP_ = (uint8_t*)fp_;
unwoundIonFrameType_ = FrameType::JSJitToWasm;

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

@ -4070,7 +4070,7 @@ bool wasm::IonCompileFunctions(const ModuleEnvironment& env, LifoAlloc& lifo,
// Compile MIR graph
{
jit::SpewBeginFunction(&mir, nullptr);
jit::SpewBeginWasmFunction(&mir, func.index);
jit::AutoSpewEndFunction spewEndFunction(&mir);
if (!OptimizeMIR(&mir)) {

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

@ -82,7 +82,7 @@ fuzzy(0-1,0-10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html
== opacity-preserve3d-5.html opacity-preserve3d-5-ref.html
== snap-perspective-1.html snap-perspective-1-ref.html
== mask-layer-1.html mask-layer-ref.html
fuzzy-if(webrender&&gtkWidget,8-8,100-100) == mask-layer-2.html mask-layer-ref.html
fuzzy-if(webrender&&gtkWidget,8-8,100-100) fuzzy-if(webrender&&cocoaWidget,1-1,16-16) == mask-layer-2.html mask-layer-ref.html
fuzzy-if(webrender,0-16,0-100) == mask-layer-3.html mask-layer-ref.html
== split-intersect1.html split-intersect1-ref.html
fuzzy(0-255,0-150) == split-intersect2.html split-intersect2-ref.html

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

@ -411,50 +411,52 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
type=str,
dest="adb_path",
default=None,
help="path to adb")
help="Path to adb binary.")
self.add_argument("--deviceSerial",
action="store",
type=str,
dest="deviceSerial",
help="adb serial number of remote device to test")
help="adb serial number of remote device. This is required "
"when more than one device is connected to the host. "
"Use 'adb devices' to see connected devices.")
self.add_argument("--remote-webserver",
action="store",
type=str,
dest="remoteWebServer",
help="IP Address of the webserver hosting the reftest content")
help="IP address of the remote web server.")
self.add_argument("--http-port",
action="store",
type=str,
dest="httpPort",
help="port of the web server for http traffic")
help="http port of the remote web server.")
self.add_argument("--ssl-port",
action="store",
type=str,
dest="sslPort",
help="Port for https traffic to the web server")
help="ssl port of the remote web server.")
self.add_argument("--remoteTestRoot",
action="store",
type=str,
dest="remoteTestRoot",
help="remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests)")
help="Remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests).")
self.add_argument("--httpd-path",
action="store",
type=str,
dest="httpdPath",
help="path to the httpd.js file")
help="Path to the httpd.js file.")
self.add_argument("--no-device-info",
action="store_false",
dest="printDeviceInfo",
default=True,
help="do not display verbose diagnostics about the remote device")
help="Do not display verbose diagnostics about the remote device.")
def validate_remote(self, options, automation):
if options.remoteWebServer is None:

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

@ -849,7 +849,9 @@ class AndroidArguments(ArgumentContainer):
args = [
[["--deviceSerial"],
{"dest": "deviceSerial",
"help": "ip address of remote device to test",
"help": "adb serial number of remote device. This is required "
"when more than one device is connected to the host. "
"Use 'adb devices' to see connected devices.",
"default": None,
}],
[["--adbpath"],
@ -861,42 +863,42 @@ class AndroidArguments(ArgumentContainer):
[["--remote-webserver"],
{"dest": "remoteWebServer",
"default": None,
"help": "ip address where the remote web server is hosted at",
"help": "IP address of the remote web server.",
}],
[["--http-port"],
{"dest": "httpPort",
"default": DEFAULT_PORTS['http'],
"help": "http port of the remote web server",
"help": "http port of the remote web server.",
"suppress": True,
}],
[["--ssl-port"],
{"dest": "sslPort",
"default": DEFAULT_PORTS['https'],
"help": "ssl port of the remote web server",
"help": "ssl port of the remote web server.",
"suppress": True,
}],
[["--robocop-apk"],
{"dest": "robocopApk",
"default": "",
"help": "name of the Robocop APK to use for ADB test running",
"help": "Name of the robocop APK to use.",
}],
[["--remoteTestRoot"],
{"dest": "remoteTestRoot",
"default": None,
"help": "remote directory to use as test root \
(eg. /mnt/sdcard/tests or /data/local/tests)",
"help": "Remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests).",
"suppress": True,
}],
[["--enable-coverage"],
{"action": "store_true",
"default": False,
"help": "Enable collecting code coverage information when running"
"help": "Enable collecting code coverage information when running "
"robocop tests.",
}],
[["--coverage-output-dir"],
{"action": "store",
"default": None,
"help": "When using --enable-java-coverage, save the code coverage report"
"help": "When using --enable-java-coverage, save the code coverage report "
"files to this directory.",
}],
]

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

@ -333,12 +333,14 @@ class JunitArgumentParser(argparse.ArgumentParser):
type=str,
dest="adbPath",
default=None,
help="Path to adb executable.")
help="Path to adb binary.")
self.add_argument("--deviceSerial",
action="store",
type=str,
dest="deviceSerial",
help="adb serial number of remote device.")
help="adb serial number of remote device. This is required "
"when more than one device is connected to the host. "
"Use 'adb devices' to see connected devices. ")
self.add_argument("--remoteTestRoot",
action="store",
type=str,
@ -410,18 +412,18 @@ class JunitArgumentParser(argparse.ArgumentParser):
type=str,
dest="httpPort",
default=DEFAULT_PORTS['http'],
help="Port of the web server for http traffic.")
help="http port of the remote web server.")
self.add_argument("--remote-webserver",
action="store",
type=str,
dest="remoteWebServer",
help="IP address of the webserver.")
help="IP address of the remote web server.")
self.add_argument("--ssl-port",
action="store",
type=str,
dest="sslPort",
default=DEFAULT_PORTS['https'],
help="Port of the web server for https traffic.")
help="ssl port of the remote web server.")
# Remaining arguments are test filters.
self.add_argument("test_filters",
nargs="*",

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

@ -171,39 +171,43 @@ class RemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):
self.add_option("--deviceSerial", action="store",
type="string", dest="device_serial",
help="serial ID of device")
help="adb serial number of remote device. This is required "
"when more than one device is connected to the host. "
"Use 'adb devices' to see connected devices.")
defaults["device_serial"] = None
self.add_option("--adbPath", action="store",
type="string", dest="adb_path",
help="Path to adb")
help="Path to adb binary.")
defaults["adb_path"] = None
self.add_option("--noSetup", action="store_false",
dest="setup",
help="do not copy any files to device (to be used only if "
"device is already setup)")
help="Do not copy any files to device (to be used only if "
"device is already setup).")
defaults["setup"] = True
self.add_option("--localLib", action="store",
type="string", dest="local_lib",
help="location of libraries to push -- preferably stripped")
help="Location of libraries to push -- preferably stripped.")
defaults["local_lib"] = None
self.add_option("--apk", action="store",
type="string", dest="local_apk",
help="local path to Fennec APK")
help="Local path to Firefox for Android APK.")
defaults["local_apk"] = None
self.add_option("--localBinDir", action="store",
type="string", dest="local_bin",
help="local path to bin directory")
help="Local path to bin directory.")
defaults[
"local_bin"] = build_obj.bindir if build_obj is not None else None
self.add_option("--remoteTestRoot", action="store",
type="string", dest="remote_test_root",
help="remote directory to use as test root (eg. /data/local/tests)")
help="Remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests).")
# /data/local/tests is used because it is usually not possible to set +x permissions
# on binaries on /mnt/sdcard
defaults["remote_test_root"] = "/data/local/tests"

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

@ -141,31 +141,33 @@ def add_common_arguments(parser):
def add_remote_arguments(parser):
parser.add_argument("--objdir", action="store", type=str, dest="objdir",
help="local objdir, containing xpcshell binaries")
help="Local objdir, containing xpcshell binaries.")
parser.add_argument("--apk", action="store", type=str, dest="localAPK",
help="local path to Fennec APK")
help="Local path to Firefox for Android APK.")
parser.add_argument("--deviceSerial", action="store", type=str, dest="deviceSerial",
help="serial ID of device")
help="adb serial number of remote device. This is required "
"when more than one device is connected to the host. "
"Use 'adb devices' to see connected devices.")
parser.add_argument("--adbPath", action="store", type=str, dest="adbPath",
default=None,
help="Path to adb")
help="Path to adb binary.")
parser.add_argument("--noSetup", action="store_false", dest="setup", default=True,
help="do not copy any files to device (to be used only if "
"device is already setup)")
help="Do not copy any files to device (to be used only if "
"device is already setup).")
parser.add_argument("--local-lib-dir", action="store", type=str, dest="localLib",
help="local path to library directory")
help="Local path to library directory.")
parser.add_argument("--local-bin-dir", action="store", type=str, dest="localBin",
help="local path to bin directory")
help="Local path to bin directory.")
parser.add_argument("--remoteTestRoot", action="store", type=str, dest="remoteTestRoot",
help="remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests)")
help="Remote directory to use as test root "
"(eg. /mnt/sdcard/tests or /data/local/tests).")
def parser_desktop():

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

@ -48,32 +48,20 @@ add_task(async function test_all_downloads() {
Assert.ok(!!download);
list.add(download);
// Second download.
download = await Downloads.createDownload({
source: { url: url.spec, isPrivate: false },
target: { path: FileTestUtils.getTempFile(TEST_TARGET_FILE_NAME).path },
let view;
let removePromise = new Promise(resolve => {
view = {
onDownloadAdded() {},
onDownloadChanged() {},
onDownloadRemoved() { resolve(); },
};
});
await download.start();
Assert.ok(!!download);
list.add(download);
await list.addView(view);
let items = await list.getAll();
Assert.equal(items.length, 2);
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_DOWNLOADS, value => {
Assert.equal(value, 0);
resolve();
});
});
items = await list.getAll();
// We don't remove the active downloads.
Assert.equal(items.length, 1);
await download.cancel();
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_DOWNLOADS, value => {
Assert.equal(value, 0);
@ -81,6 +69,8 @@ add_task(async function test_all_downloads() {
});
});
await removePromise;
items = await list.getAll();
Assert.equal(items.length, 0);
});
@ -103,6 +93,17 @@ add_task(async function test_range_downloads() {
let items = await list.getAll();
Assert.equal(items.length, 1);
let view;
let removePromise = new Promise(resolve => {
view = {
onDownloadAdded() {},
onDownloadChanged() {},
onDownloadRemoved() { resolve(); },
};
});
await list.addView(view);
await new Promise(resolve => {
Services.clearData.deleteDataInTimeRange(download.startTime.getTime() * 1000,
download.startTime.getTime() * 1000,
@ -113,6 +114,8 @@ add_task(async function test_range_downloads() {
});
});
await removePromise;
items = await list.getAll();
Assert.equal(items.length, 0);
});
@ -137,6 +140,17 @@ add_task(async function test_principal_downloads() {
let items = await list.getAll();
Assert.equal(items.length, 2);
let view;
let removePromise = new Promise(resolve => {
view = {
onDownloadAdded() {},
onDownloadChanged() {},
onDownloadRemoved() { resolve(); },
};
});
await list.addView(view);
let uri = Services.io.newURI("http://example.com");
let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
@ -149,9 +163,21 @@ add_task(async function test_principal_downloads() {
});
});
await removePromise;
items = await list.getAll();
Assert.equal(items.length, 1);
removePromise = new Promise(resolve => {
view = {
onDownloadAdded() {},
onDownloadChanged() {},
onDownloadRemoved() { resolve(); },
};
});
await list.addView(view);
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_DOWNLOADS, value => {
Assert.equal(value, 0);
@ -159,6 +185,8 @@ add_task(async function test_principal_downloads() {
});
});
await removePromise;
items = await list.getAll();
Assert.equal(items.length, 0);
});