Bug 1064358 - Recover CreateThisWithTemplate. r=jandem

This commit is contained in:
Nicolas B. Pierron 2014-09-25 19:12:55 +02:00
parent f3e5d3181a
commit c8abcdcbb9
8 changed files with 126 additions and 11 deletions

View File

@ -1,5 +1,5 @@
setJitCompilerOption("baseline.warmup.trigger", 10);
setJitCompilerOption("ion.warmup.trigger", 20);
setJitCompilerOption("ion.warmup.trigger", 30);
var uceFault = function (i) {
if (i > 98)
@ -112,6 +112,20 @@ function dynamicSlots(i) {
assertEq(obj.p0 + obj.p10 + obj.p20 + obj.p30 + obj.p40, 5 * i + 100);
}
// Check that we can correctly recover allocations of new objects.
function Point(x, y)
{
this.x = x;
this.y = y;
}
function createThisWithTemplate(i)
{
var p = new Point(i - 1, i + 1);
bailout();
assertEq(p.y - p.x, 2);
}
for (var i = 0; i < 100; i++) {
notSoEmpty1(i);
@ -121,4 +135,5 @@ for (var i = 0; i < 100; i++) {
withinIf(i);
unknownLoad(i);
dynamicSlots(i);
createThisWithTemplate(i);
}

View File

@ -5171,9 +5171,11 @@ IonBuilder::createThisScriptedSingleton(JSFunction *target, MDefinition *callee)
// Generate an inline path to create a new |this| object with
// the given singleton prototype.
MConstant *templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
MCreateThisWithTemplate *createThis =
MCreateThisWithTemplate::New(alloc(), constraints(), templateObject,
MCreateThisWithTemplate::New(alloc(), constraints(), templateConst,
templateObject->type()->initialHeap(constraints()));
current->add(templateConst);
current->add(createThis);
return createThis;

View File

@ -3167,6 +3167,14 @@ MNewObject::shouldUseVM() const
return obj->hasSingletonType() || obj->hasDynamicSlots();
}
bool
MCreateThisWithTemplate::canRecoverOnBailout() const
{
MOZ_ASSERT(!templateObject()->denseElementsAreCopyOnWrite());
MOZ_ASSERT(!templateObject()->is<ArrayObject>());
return true;
}
MObjectState::MObjectState(MDefinition *obj)
{
// This instruction is only used as a summary for bailout paths.

View File

@ -3629,31 +3629,30 @@ class MAssertRange
// Caller-side allocation of |this| for |new|:
// Given a templateobject, construct |this| for JSOP_NEW
class MCreateThisWithTemplate
: public MNullaryInstruction
: public MUnaryInstruction
{
// Template for |this|, provided by TI
AlwaysTenuredObject templateObject_;
gc::InitialHeap initialHeap_;
MCreateThisWithTemplate(types::CompilerConstraintList *constraints, JSObject *templateObject,
MCreateThisWithTemplate(types::CompilerConstraintList *constraints, MConstant *templateConst,
gc::InitialHeap initialHeap)
: templateObject_(templateObject),
: MUnaryInstruction(templateConst),
initialHeap_(initialHeap)
{
setResultType(MIRType_Object);
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject));
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
}
public:
INSTRUCTION_HEADER(CreateThisWithTemplate);
static MCreateThisWithTemplate *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
JSObject *templateObject, gc::InitialHeap initialHeap)
MConstant *templateConst, gc::InitialHeap initialHeap)
{
return new(alloc) MCreateThisWithTemplate(constraints, templateObject, initialHeap);
return new(alloc) MCreateThisWithTemplate(constraints, templateConst, initialHeap);
}
// Template for |this|, provided by TI.
JSObject *templateObject() const {
return templateObject_;
return &getOperand(0)->toConstant()->value().toObject();
}
gc::InitialHeap initialHeap() const {
@ -3664,6 +3663,9 @@ class MCreateThisWithTemplate
AliasSet getAliasSet() const {
return AliasSet::None();
}
bool writeRecoverData(CompactBufferWriter &writer) const;
bool canRecoverOnBailout() const;
};
// Caller-side allocation of |this| for |new|:

View File

@ -14,6 +14,8 @@
#include "builtin/RegExp.h"
#include "builtin/TypedObject.h"
#include "gc/Heap.h"
#include "jit/JitFrameIterator.h"
#include "jit/JitSpewer.h"
#include "jit/MIR.h"
@ -1094,6 +1096,42 @@ RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const
return true;
}
bool
MCreateThisWithTemplate::writeRecoverData(CompactBufferWriter &writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_CreateThisWithTemplate));
writer.writeByte(bool(initialHeap() == gc::TenuredHeap));
return true;
}
RCreateThisWithTemplate::RCreateThisWithTemplate(CompactBufferReader &reader)
{
tenuredHeap_ = reader.readByte();
}
bool
RCreateThisWithTemplate::recover(JSContext *cx, SnapshotIterator &iter) const
{
RootedObject templateObject(cx, &iter.read().toObject());
// Use AutoEnterAnalysis to avoid invoking the object metadata callback
// while bailing out, which could try to walk the stack.
types::AutoEnterAnalysis enter(cx);
// See CodeGenerator::visitCreateThisWithTemplate
gc::AllocKind allocKind = templateObject->asTenured()->getAllocKind();
gc::InitialHeap initialHeap = tenuredHeap_ ? gc::TenuredHeap : gc::DefaultHeap;
JSObject *resultObject = JSObject::copy(cx, allocKind, initialHeap, templateObject);
if (!resultObject)
return false;
RootedValue result(cx);
result.setObject(*resultObject);
iter.storeInstructionResult(result);
return true;
}
bool
MObjectState::writeRecoverData(CompactBufferWriter &writer) const
{

View File

@ -54,6 +54,7 @@ namespace jit {
_(NewObject) \
_(NewArray) \
_(NewDerivedTypedObject) \
_(CreateThisWithTemplate) \
_(ObjectState) \
_(ArrayState)
@ -557,6 +558,21 @@ class RNewDerivedTypedObject MOZ_FINAL : public RInstruction
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RCreateThisWithTemplate MOZ_FINAL : public RInstruction
{
private:
bool tenuredHeap_;
public:
RINSTRUCTION_HEADER_(CreateThisWithTemplate)
virtual uint32_t numOperands() const {
return 1;
}
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RObjectState MOZ_FINAL : public RInstruction
{
private:

View File

@ -241,6 +241,11 @@ class JSObject : public js::ObjectImpl
js::HandleShape shape,
js::HandleTypeObject type);
static inline JSObject *copy(js::ExclusiveContext *cx,
js::gc::AllocKind kind,
js::gc::InitialHeap heap,
js::HandleObject templateObject);
/* Make an array object with the specified initial state. */
static inline js::ArrayObject *createArray(js::ExclusiveContext *cx,
js::gc::AllocKind kind,

View File

@ -548,6 +548,35 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
return obj;
}
/* static */ inline JSObject *
JSObject::copy(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
js::HandleObject templateObject)
{
js::RootedShape shape(cx, templateObject->lastProperty());
js::RootedTypeObject type(cx, templateObject->type());
MOZ_ASSERT(!templateObject->denseElementsAreCopyOnWrite());
JSObject *obj = create(cx, kind, heap, shape, type);
if (!obj)
return nullptr;
size_t span = shape->slotSpan();
if (span) {
uint32_t numFixed = templateObject->numFixedSlots();
const js::Value *fixed = &templateObject->getSlot(0);
MOZ_ASSERT(numFixed <= span);
obj->copySlotRange(0, fixed, numFixed);
if (numFixed < span) {
uint32_t numSlots = span - numFixed;
const js::Value *slots = &templateObject->getSlot(numFixed);
obj->copySlotRange(numFixed, slots, numSlots);
}
}
return obj;
}
/* static */ inline JSObject *
JSObject::createArrayInternal(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
js::HandleShape shape, js::HandleTypeObject type)