Bug 1233176 - Scalar Replacement: Initialize properties with the default value of the template object. r=shu

This commit is contained in:
Nicolas B. Pierron 2015-12-22 13:22:22 +00:00
Родитель 1b186ddd18
Коммит 9aef99a4e0
4 изменённых файлов: 96 добавлений и 6 удалений

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

@ -0,0 +1,39 @@
// This function uses UCE to test when the if branch is removed by
// IonMonkey. Some optimization such as Scalar Replacement are able to remove
// the scope chain, which can cause issues when the scope chain properties are
// not initialized properly.
var uceFault = function (i) {
if (i % 1500 == 0) {
uceFault = function (i) { return i % 1500 == 0; };
}
return false;
};
function f(i) {
if (uceFault(i) || uceFault(i))
g();
const x = 42;
function g() {
return x;
}
return g;
}
function loop() {
for (; i < 4000; i++)
assertEq(f(i)(), 42);
}
var caught = 0;
var i = 1;
while (i < 4000) {
try {
loop();
} catch(e) {
assertEq(e instanceof ReferenceError, true);
assertEq(i == 1500 || i == 3000, true);
caught += 1;
i++;
}
}
assertEq(caught, 2);

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

@ -3993,7 +3993,6 @@ OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject)
const UnboxedLayout& layout =
templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
// 0 is used as an error code.
const UnboxedLayout::PropertyVector& properties = layout.properties();
MOZ_ASSERT(properties.length() < 255);
@ -4068,8 +4067,54 @@ MObjectState::init(TempAllocator& alloc, MDefinition* obj)
return true;
}
bool
MObjectState::initFromTemplateObject(TempAllocator& alloc, MDefinition* undefinedVal)
{
JSObject* templateObject = templateObjectOf(object());
// Initialize all the slots of the object state with the value contained in
// the template object. This is needed to account values which are baked in
// the template objects and not visible in IonMonkey, such as the
// uninitialized-lexical magic value of call objects.
if (templateObject->is<UnboxedPlainObject>()) {
UnboxedPlainObject& unboxedObject = templateObject->as<UnboxedPlainObject>();
const UnboxedLayout& layout = unboxedObject.layoutDontCheckGeneration();
const UnboxedLayout::PropertyVector& properties = layout.properties();
for (size_t i = 0; i < properties.length(); i++) {
Value val = unboxedObject.getValue(properties[i], /* maybeUninitialized = */ true);
MDefinition *def = undefinedVal;
if (!val.isUndefined()) {
MConstant* ins = val.isObject() ?
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
MConstant::New(alloc, val);
block()->insertBefore(this, ins);
def = ins;
}
initSlot(i, def);
}
} else {
NativeObject& nativeObject = templateObject->as<NativeObject>();
MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
for (size_t i = 0; i < numSlots(); i++) {
Value val = nativeObject.getSlot(i);
MDefinition *def = undefinedVal;
if (!val.isUndefined()) {
MConstant* ins = val.isObject() ?
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
MConstant::New(alloc, val);
block()->insertBefore(this, ins);
def = ins;
}
initSlot(i, def);
}
}
return true;
}
MObjectState*
MObjectState::New(TempAllocator& alloc, MDefinition* obj, MDefinition* undefinedVal)
MObjectState::New(TempAllocator& alloc, MDefinition* obj)
{
JSObject* templateObject = templateObjectOf(obj);
MOZ_ASSERT(templateObject, "Unexpected object creation.");
@ -4084,8 +4129,6 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj, MDefinition* undefined
MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex);
if (!res || !res->init(alloc, obj))
return nullptr;
for (size_t i = 0; i < res->numSlots(); i++)
res->initSlot(i, undefinedVal);
return res;
}

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

@ -3399,9 +3399,13 @@ class MObjectState
// on bailout.
static JSObject* templateObjectOf(MDefinition* obj);
static MObjectState* New(TempAllocator& alloc, MDefinition* obj, MDefinition* undefinedVal);
static MObjectState* New(TempAllocator& alloc, MDefinition* obj);
static MObjectState* Copy(TempAllocator& alloc, MObjectState* state);
// As we might do read of uninitialized properties, we have to copy the
// initial values from the template object.
bool initFromTemplateObject(TempAllocator& alloc, MDefinition* undefinedVal);
MDefinition* object() const {
return getOperand(0);
}

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

@ -349,12 +349,16 @@ ObjectMemoryView::initStartingState(BlockState** pState)
startBlock_->insertBefore(obj_, undefinedVal_);
// Create a new block state and insert at it at the location of the new object.
BlockState* state = BlockState::New(alloc_, obj_, undefinedVal_);
BlockState* state = BlockState::New(alloc_, obj_);
if (!state)
return false;
startBlock_->insertAfter(obj_, state);
// Initialize the properties of the object state.
if (!state->initFromTemplateObject(alloc_, undefinedVal_))
return false;
// Hold out of resume point until it is visited.
state->setInWorklist();