Bug 1688033: Add forwarded argument flag to ArgumentsObject r=jandem

Being able to test whether an ArgumentsObject has closed-over arguments by checking a flag instead of testing each argument makes future patches significantly simpler.

I considered just making closed-over arguments set ELEMENT_OVERRIDDEN_BIT, but this would make ArgumentsObjectArg fail if *any* argument was closed over, even if the specific argument we are loading is not.

Depends on D104483

Differential Revision: https://phabricator.services.mozilla.com/D104484
This commit is contained in:
Iain Ireland 2021-02-12 20:28:46 +00:00
Родитель 7159fa8127
Коммит d5fecbb0dc
3 изменённых файлов: 31 добавлений и 1 удалений

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

@ -0,0 +1,14 @@
function bar(x,y) {
return x + y;
}
function foo(x, y) {
function closeOver() { return x; }
return bar.apply({}, arguments);
}
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += foo(1,2);
}
assertEq(sum, 300)

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

@ -99,6 +99,7 @@ void ArgumentsObject::MaybeForwardToCallObject(AbstractFramePtr frame,
for (PositionalFormalParameterIter fi(script); fi; fi++) { for (PositionalFormalParameterIter fi(script); fi; fi++) {
if (fi.closedOver()) { if (fi.closedOver()) {
data->args[fi.argumentSlot()] = MagicEnvSlotValue(fi.location().slot()); data->args[fi.argumentSlot()] = MagicEnvSlotValue(fi.location().slot());
obj->markArgumentForwarded();
} }
} }
} }
@ -117,6 +118,7 @@ void ArgumentsObject::MaybeForwardToCallObject(jit::JitFrameLayout* frame,
for (PositionalFormalParameterIter fi(script); fi; fi++) { for (PositionalFormalParameterIter fi(script); fi; fi++) {
if (fi.closedOver()) { if (fi.closedOver()) {
data->args[fi.argumentSlot()] = MagicEnvSlotValue(fi.location().slot()); data->args[fi.argumentSlot()] = MagicEnvSlotValue(fi.location().slot());
obj->markArgumentForwarded();
} }
} }
} }

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

@ -168,7 +168,9 @@ class ArgumentsObject : public NativeObject {
static const uint32_t ITERATOR_OVERRIDDEN_BIT = 0x2; static const uint32_t ITERATOR_OVERRIDDEN_BIT = 0x2;
static const uint32_t ELEMENT_OVERRIDDEN_BIT = 0x4; static const uint32_t ELEMENT_OVERRIDDEN_BIT = 0x4;
static const uint32_t CALLEE_OVERRIDDEN_BIT = 0x8; static const uint32_t CALLEE_OVERRIDDEN_BIT = 0x8;
static const uint32_t PACKED_BITS_COUNT = 4; static const uint32_t FORWARDED_ARGUMENTS_BIT = 0x10;
static const uint32_t PACKED_BITS_COUNT = 5;
static const uint32_t PACKED_BITS_MASK = (1 << PACKED_BITS_COUNT) - 1;
static_assert(ARGS_LENGTH_MAX <= (UINT32_MAX >> PACKED_BITS_COUNT), static_assert(ARGS_LENGTH_MAX <= (UINT32_MAX >> PACKED_BITS_COUNT),
"Max arguments length must fit in available bits"); "Max arguments length must fit in available bits");
@ -370,9 +372,21 @@ class ArgumentsObject : public NativeObject {
bool argIsForwarded(unsigned i) const { bool argIsForwarded(unsigned i) const {
MOZ_ASSERT(i < data()->numArgs); MOZ_ASSERT(i < data()->numArgs);
const Value& v = data()->args[i]; const Value& v = data()->args[i];
MOZ_ASSERT_IF(IsMagicScopeSlotValue(v), anyArgIsForwarded());
return IsMagicScopeSlotValue(v); return IsMagicScopeSlotValue(v);
} }
bool anyArgIsForwarded() const {
const Value& v = getFixedSlot(INITIAL_LENGTH_SLOT);
return v.toInt32() & FORWARDED_ARGUMENTS_BIT;
}
void markArgumentForwarded() {
uint32_t v =
getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() | FORWARDED_ARGUMENTS_BIT;
setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
}
/* /*
* Attempt to speedily and efficiently access the i-th element of this * Attempt to speedily and efficiently access the i-th element of this
* arguments object. Return true if the element was speedily returned. * arguments object. Return true if the element was speedily returned.