Skip to content

Commit

Permalink
Bug 1041688 - Add acquired properties analysis, r=jandem.
Browse files Browse the repository at this point in the history
  • Loading branch information
bhackett1024 committed Sep 2, 2014
1 parent 99c54d4 commit e33a8eb
Show file tree
Hide file tree
Showing 23 changed files with 1,054 additions and 416 deletions.
2 changes: 1 addition & 1 deletion js/src/gc/Barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ class JitCode;
}
namespace types {
struct TypeObject;
struct TypeNewScript;
class TypeNewScript;
}

typedef PreBarriered<JSObject*> PreBarrieredObject;
Expand Down
12 changes: 4 additions & 8 deletions js/src/gc/Marking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,10 +1437,8 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
if (type->singleton() && !type->lazy())
PushMarkStack(gcmarker, type->singleton());

if (type->newScript()) {
PushMarkStack(gcmarker, type->newScript()->fun);
PushMarkStack(gcmarker, type->newScript()->templateObject);
}
if (type->newScript())
type->newScript()->trace(gcmarker);

if (type->interpretedFunction)
PushMarkStack(gcmarker, type->interpretedFunction);
Expand All @@ -1462,10 +1460,8 @@ gc::MarkChildren(JSTracer *trc, types::TypeObject *type)
if (type->singleton() && !type->lazy())
MarkObject(trc, &type->singletonRaw(), "type_singleton");

if (type->newScript()) {
MarkObject(trc, &type->newScript()->fun, "type_new_function");
MarkObject(trc, &type->newScript()->templateObject, "type_new_template");
}
if (type->newScript())
type->newScript()->trace(trc);

if (type->interpretedFunction)
MarkObject(trc, &type->interpretedFunction, "type_function");
Expand Down
2 changes: 1 addition & 1 deletion js/src/gdb/tests/test-Root.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "gdb-tests.h"

#include "jsapi.h"
#include "jsobj.h"
#include "jsfun.h"

#include "gc/Barrier.h"

Expand Down
105 changes: 96 additions & 9 deletions js/src/jit/BaselineIC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ ICStub::trace(JSTracer *trc)
ICSetProp_NativeAdd *propStub = toSetProp_NativeAdd();
MarkTypeObject(trc, &propStub->type(), "baseline-setpropnativeadd-stub-type");
MarkShape(trc, &propStub->newShape(), "baseline-setpropnativeadd-stub-newshape");
if (propStub->newType())
MarkTypeObject(trc, &propStub->newType(), "baseline-setpropnativeadd-stub-new-type");
JS_STATIC_ASSERT(ICSetProp_NativeAdd::MAX_PROTO_CHAIN_DEPTH == 4);
switch (propStub->protoChainDepth()) {
case 0: propStub->toImpl<0>()->traceShapes(trc); break;
Expand Down Expand Up @@ -6210,6 +6212,39 @@ UpdateExistingGenerationalDOMProxyStub(ICGetProp_Fallback *stub,
return false;
}

static bool
HasUnanalyzedNewScript(JSObject *obj)
{
if (obj->hasSingletonType())
return false;

types::TypeNewScript *newScript = obj->type()->newScript();
if (newScript && !newScript->analyzed())
return true;

return false;
}

static void
StripPreliminaryObjectStubs(JSContext *cx, ICFallbackStub *stub)
{
// Before the new script properties analysis has been performed on a type,
// all instances of that type have the maximum number of fixed slots.
// Afterwards, the objects (even the preliminary ones) might be changed
// to reduce the number of fixed slots they have. If we generate stubs for
// both the old and new number of fixed slots, the stub will look
// polymorphic to IonBuilder when it is actually monomorphic. To avoid
// this, strip out any stubs for preliminary objects before attaching a new
// stub which isn't on a preliminary object.

for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
if (iter->isGetProp_Native() && iter->toGetProp_Native()->hasPreliminaryObject())
iter.unlink(cx);
else if (iter->isSetProp_Native() && iter->toSetProp_Native()->hasPreliminaryObject())
iter.unlink(cx);
}
}

static bool
TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
ICGetProp_Fallback *stub, HandlePropertyName name,
Expand Down Expand Up @@ -6256,10 +6291,15 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
(obj == holder) ? "direct" : "prototype");
ICGetPropNativeCompiler compiler(cx, kind, isCallProp, monitorStub, obj, holder,
name, isFixedSlot, offset);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
ICGetPropNativeStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;

if (HasUnanalyzedNewScript(obj))
newStub->notePreliminaryObject();
else
StripPreliminaryObjectStubs(cx, stub);

stub->addNewStub(newStub);
*attached = true;
return true;
Expand Down Expand Up @@ -7414,7 +7454,7 @@ BaselineScript::noteAccessedGetter(uint32_t pcOffset)
// Attach an optimized stub for a SETPROP/SETGNAME/SETNAME op.
static bool
TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetProp_Fallback *stub,
HandleObject obj, HandleShape oldShape, uint32_t oldSlots,
HandleObject obj, HandleShape oldShape, HandleTypeObject oldType, uint32_t oldSlots,
HandlePropertyName name, HandleId id, HandleValue rhs, bool *attached)
{
JS_ASSERT(!*attached);
Expand All @@ -7433,12 +7473,22 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
if (chainDepth > ICSetProp_NativeAdd::MAX_PROTO_CHAIN_DEPTH)
return true;

// Don't attach if we are adding a property to an object which the new
// script properties analysis hasn't been performed for yet, as there
// may be a shape change required here afterwards. Pretend we attached
// a stub, though, so the access is not marked as unoptimizable.
if (oldType->newScript() && !oldType->newScript()->analyzed()) {
*attached = true;
return true;
}

bool isFixedSlot;
uint32_t offset;
GetFixedOrDynamicSlotOffset(obj, shape->slot(), &isFixedSlot, &offset);

JitSpew(JitSpew_BaselineIC, " Generating SetProp(NativeObject.ADD) stub");
ICSetPropNativeAddCompiler compiler(cx, obj, oldShape, chainDepth, isFixedSlot, offset);
ICSetPropNativeAddCompiler compiler(cx, obj, oldShape, oldType,
chainDepth, isFixedSlot, offset);
ICUpdatedStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
Expand All @@ -7457,12 +7507,17 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr

JitSpew(JitSpew_BaselineIC, " Generating SetProp(NativeObject.PROP) stub");
ICSetProp_Native::Compiler compiler(cx, obj, isFixedSlot, offset);
ICUpdatedStub *newStub = compiler.getStub(compiler.getStubSpace(script));
ICSetProp_Native *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
if (!newStub->addUpdateStubForValue(cx, script, obj, id, rhs))
return false;

if (HasUnanalyzedNewScript(obj))
newStub->notePreliminaryObject();
else
StripPreliminaryObjectStubs(cx, stub);

stub->addNewStub(newStub);
*attached = true;
return true;
Expand Down Expand Up @@ -7541,6 +7596,9 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
if (!obj)
return false;
RootedShape oldShape(cx, obj->lastProperty());
RootedTypeObject oldType(cx, obj->getType(cx));
if (!oldType)
return false;
uint32_t oldSlots = obj->numDynamicSlots();

if (op == JSOP_INITPROP) {
Expand Down Expand Up @@ -7577,8 +7635,8 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
}

bool attached = false;
if (!TryAttachSetPropStub(cx, script, pc, stub, obj, oldShape, oldSlots, name, id, rhs,
&attached))
if (!TryAttachSetPropStub(cx, script, pc, stub, obj, oldShape, oldType, oldSlots,
name, id, rhs, &attached))
{
return false;
}
Expand Down Expand Up @@ -7799,6 +7857,15 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewShape()), scratch);
masm.storePtr(scratch, shapeAddr);

// Change the object's type if required.
Label noTypeChange;
masm.loadPtr(Address(BaselineStubReg, ICSetProp_NativeAdd::offsetOfNewType()), scratch);
masm.branchTestPtr(Assembler::Zero, scratch, scratch, &noTypeChange);
Address typeAddr(objReg, JSObject::offsetOfType());
EmitPreBarrier(masm, typeAddr, MIRType_TypeObject);
masm.storePtr(scratch, typeAddr);
masm.bind(&noTypeChange);

Register holderReg;
regs.add(R0);
regs.takeUnchecked(objReg);
Expand Down Expand Up @@ -8272,6 +8339,21 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
templateObject = CreateThisForFunction(cx, fun, MaybeSingletonObject);
if (!templateObject)
return false;

// If we are calling a constructor for which the new script
// properties analysis has not been performed yet, don't attach a
// stub. After the analysis is performed, CreateThisForFunction may
// start returning objects with a different type, and the Ion
// compiler might get confused.
if (templateObject->type()->newScript() &&
!templateObject->type()->newScript()->analyzed())
{
// Clear the object just created from the preliminary objects
// on the TypeNewScript, as it will not be used or filled in by
// running code.
templateObject->type()->newScript()->unregisterNewObject(templateObject);
return true;
}
}

JitSpew(JitSpew_BaselineIC,
Expand Down Expand Up @@ -10496,15 +10578,15 @@ ICSetProp_Native::ICSetProp_Native(JitCode *stubCode, HandleTypeObject type, Han
offset_(offset)
{ }

ICUpdatedStub *
ICSetProp_Native *
ICSetProp_Native::Compiler::getStub(ICStubSpace *space)
{
RootedTypeObject type(cx, obj_->getType(cx));
if (!type)
return nullptr;

RootedShape shape(cx, obj_->lastProperty());
ICUpdatedStub *stub = ICSetProp_Native::New(space, getStubCode(), type, shape, offset_);
ICSetProp_Native *stub = ICSetProp_Native::New(space, getStubCode(), type, shape, offset_);
if (!stub || !stub->initUpdatingChain(cx, space))
return nullptr;
return stub;
Expand All @@ -10513,10 +10595,12 @@ ICSetProp_Native::Compiler::getStub(ICStubSpace *space)
ICSetProp_NativeAdd::ICSetProp_NativeAdd(JitCode *stubCode, HandleTypeObject type,
size_t protoChainDepth,
HandleShape newShape,
HandleTypeObject newType,
uint32_t offset)
: ICUpdatedStub(SetProp_NativeAdd, stubCode),
type_(type),
newShape_(newShape),
newType_(newType),
offset_(offset)
{
JS_ASSERT(protoChainDepth <= MAX_PROTO_CHAIN_DEPTH);
Expand All @@ -10528,8 +10612,9 @@ ICSetProp_NativeAddImpl<ProtoChainDepth>::ICSetProp_NativeAddImpl(JitCode *stubC
HandleTypeObject type,
const AutoShapeVector *shapes,
HandleShape newShape,
HandleTypeObject newType,
uint32_t offset)
: ICSetProp_NativeAdd(stubCode, type, ProtoChainDepth, newShape, offset)
: ICSetProp_NativeAdd(stubCode, type, ProtoChainDepth, newShape, newType, offset)
{
JS_ASSERT(shapes->length() == NumShapes);
for (size_t i = 0; i < NumShapes; i++)
Expand All @@ -10538,12 +10623,14 @@ ICSetProp_NativeAddImpl<ProtoChainDepth>::ICSetProp_NativeAddImpl(JitCode *stubC

ICSetPropNativeAddCompiler::ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj,
HandleShape oldShape,
HandleTypeObject oldType,
size_t protoChainDepth,
bool isFixedSlot,
uint32_t offset)
: ICStubCompiler(cx, ICStub::SetProp_NativeAdd),
obj_(cx, obj),
oldShape_(cx, oldShape),
oldType_(cx, oldType),
protoChainDepth_(protoChainDepth),
isFixedSlot_(isFixedSlot),
offset_(offset)
Expand Down
Loading

0 comments on commit e33a8eb

Please sign in to comment.