Backed out changeset b4ebfef56fee (bug 922270) for SM(r) failures.

This commit is contained in:
Ryan VanderMeulen 2013-10-16 16:21:03 -04:00
parent 4dc9ae61b0
commit 83dc48b96b
13 changed files with 164 additions and 296 deletions

View File

@ -1140,7 +1140,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
switch (type->addendum->kind) {
case types::TypeObjectAddendum::NewScript:
PushMarkStack(gcmarker, type->newScript()->fun);
PushMarkStack(gcmarker, type->newScript()->templateObject);
PushMarkStack(gcmarker, type->newScript()->shape.get());
break;
case types::TypeObjectAddendum::TypedObject:
@ -1173,7 +1173,7 @@ gc::MarkChildren(JSTracer *trc, types::TypeObject *type)
switch (type->addendum->kind) {
case types::TypeObjectAddendum::NewScript:
MarkObject(trc, &type->newScript()->fun, "type_new_function");
MarkObject(trc, &type->newScript()->templateObject, "type_new_template");
MarkShape(trc, &type->newScript()->shape, "type_new_shape");
break;
case types::TypeObjectAddendum::TypedObject:

View File

@ -1393,12 +1393,7 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
masm.move32(Imm32(length), R0.scratchReg());
masm.movePtr(ImmGCPtr(type), R1.scratchReg());
JSObject *templateObject = NewDenseUnallocatedArray(cx, length);
if (!templateObject)
return false;
templateObject->setType(type);
ICNewArray_Fallback::Compiler stubCompiler(cx, templateObject);
ICNewArray_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@ -1450,7 +1445,10 @@ BaselineCompiler::emit_JSOP_NEWOBJECT()
return false;
}
ICNewObject_Fallback::Compiler stubCompiler(cx, templateObject);
// Pass base object in R0.
masm.movePtr(ImmGCPtr(templateObject), R0.scratchReg());
ICNewObject_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
@ -1476,12 +1474,7 @@ BaselineCompiler::emit_JSOP_NEWINIT()
masm.move32(Imm32(0), R0.scratchReg());
masm.movePtr(ImmGCPtr(type), R1.scratchReg());
JSObject *templateObject = NewDenseUnallocatedArray(cx, 0);
if (!templateObject)
return false;
templateObject->setType(type);
ICNewArray_Fallback::Compiler stubCompiler(cx, templateObject);
ICNewArray_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
} else {
@ -1499,7 +1492,10 @@ BaselineCompiler::emit_JSOP_NEWINIT()
return false;
}
ICNewObject_Fallback::Compiler stubCompiler(cx, templateObject);
// Pass base object in R0.
masm.movePtr(ImmGCPtr(templateObject), R0.scratchReg());
ICNewObject_Fallback::Compiler stubCompiler(cx);
if (!emitOpIC(stubCompiler.getStub(&stubSpace_)))
return false;
}

View File

@ -29,7 +29,6 @@
#include "jit/IonFrames-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/ScopeObject-inl.h"
#include "vm/StringObject-inl.h"
namespace js {
namespace jit {
@ -184,15 +183,11 @@ ICStub::trace(JSTracer *trc)
case ICStub::Call_Scripted: {
ICCall_Scripted *callStub = toCall_Scripted();
MarkScript(trc, &callStub->calleeScript(), "baseline-callscripted-callee");
if (callStub->templateObject())
MarkObject(trc, &callStub->templateObject(), "baseline-callscripted-template");
break;
}
case ICStub::Call_Native: {
ICCall_Native *callStub = toCall_Native();
MarkObject(trc, &callStub->callee(), "baseline-callnative-callee");
if (callStub->templateObject())
MarkObject(trc, &callStub->templateObject(), "baseline-callnative-template");
break;
}
case ICStub::GetElem_NativeSlot: {
@ -406,16 +401,6 @@ ICStub::trace(JSTracer *trc)
MarkObject(trc, &callStub->setter(), "baseline-setpropcallnative-stub-setter");
break;
}
case ICStub::NewArray_Fallback: {
ICNewArray_Fallback *stub = toNewArray_Fallback();
MarkObject(trc, &stub->templateObject(), "baseline-newarray-template");
break;
}
case ICStub::NewObject_Fallback: {
ICNewObject_Fallback *stub = toNewObject_Fallback();
MarkObject(trc, &stub->templateObject(), "baseline-newobject-template");
break;
}
default:
break;
}
@ -1698,11 +1683,11 @@ ICNewArray_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
//
static bool
DoNewObject(JSContext *cx, ICNewObject_Fallback *stub, MutableHandleValue res)
DoNewObject(JSContext *cx, ICNewObject_Fallback *stub, HandleObject templateObject,
MutableHandleValue res)
{
FallbackICSpew(cx, stub, "NewObject");
RootedObject templateObject(cx, stub->templateObject());
JSObject *obj = NewInitObject(cx, templateObject);
if (!obj)
return false;
@ -1711,7 +1696,8 @@ DoNewObject(JSContext *cx, ICNewObject_Fallback *stub, MutableHandleValue res)
return true;
}
typedef bool(*DoNewObjectFn)(JSContext *, ICNewObject_Fallback *, MutableHandleValue);
typedef bool(*DoNewObjectFn)(JSContext *, ICNewObject_Fallback *, HandleObject,
MutableHandleValue);
static const VMFunction DoNewObjectInfo = FunctionInfo<DoNewObjectFn>(DoNewObject);
bool
@ -1719,6 +1705,7 @@ ICNewObject_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
{
EmitRestoreTailCallReg(masm);
masm.push(R0.scratchReg()); // template
masm.push(BaselineStubReg); // stub.
return tailCallVM(DoNewObjectInfo, masm);
@ -7429,51 +7416,6 @@ TryAttachFunApplyStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script,
return true;
}
static bool
GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc,
Native native, const CallArgs &args, MutableHandleObject res)
{
// Check for natives to which template objects can be attached. This is
// done to provide templates to Ion for inlining these natives later on.
if (native == js_Array) {
size_t count = 0;
if (args.hasDefined(1))
count = args.length();
else if (args.hasDefined(0) && args[0].isInt32() && args[0].toInt32() > 0)
count = args[0].toInt32();
res.set(NewDenseUnallocatedArray(cx, count, nullptr, TenuredObject));
if (!res)
return false;
types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
if (!type)
return false;
res->setType(type);
return true;
}
if (native == js::array_concat) {
if (args.thisv().isObject() && args.thisv().toObject().is<ArrayObject>()) {
res.set(NewDenseEmptyArray(cx, args.thisv().toObject().getProto(), TenuredObject));
if (!res)
return false;
res->setType(args.thisv().toObject().type());
return true;
}
}
if (native == js_String) {
RootedString emptyString(cx, cx->runtime()->emptyString);
res.set(StringObject::create(cx, emptyString, TenuredObject));
if (!res)
return false;
return true;
}
return true;
}
static bool
TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsbytecode *pc,
JSOp op, uint32_t argc, Value *vp, bool constructing, bool useNewType)
@ -7546,23 +7488,12 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
if (IsIonEnabled(cx))
types::EnsureTrackPropertyTypes(cx, fun, NameToId(cx->names().prototype));
// Remember the template object associated with any script being called
// as a constructor, for later use during Ion compilation.
RootedObject templateObject(cx);
if (constructing) {
if (!fun->hasLazyType() && fun->type()->hasNewScript())
templateObject = fun->type()->newScript()->templateObject;
else
templateObject = CreateThisForFunction(cx, fun, /* newType = */ false);
}
IonSpew(IonSpew_BaselineIC,
" Generating Call_Scripted stub (fun=%p, %s:%d, cons=%s)",
fun.get(), fun->nonLazyScript()->filename(), fun->nonLazyScript()->lineno,
constructing ? "yes" : "no");
ICCallScriptedCompiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
calleeScript, templateObject,
constructing, pc - script->code);
calleeScript, constructing, pc - script->code);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
@ -7572,12 +7503,12 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
}
if (fun->isNative() && (!constructing || (constructing && fun->isNativeConstructor()))) {
// Generalized native call stubs are not here yet!
// Generalied native call stubs are not here yet!
JS_ASSERT(!stub->nativeStubsAreGeneralized());
// Check for JSOP_FUNAPPLY
if (op == JSOP_FUNAPPLY) {
if (fun->native() == js_fun_apply)
if (fun->maybeNative() == js_fun_apply)
return TryAttachFunApplyStub(cx, stub, script, pc, thisv, argc, vp + 2);
// Don't try to attach a "regular" optimized call stubs for FUNAPPLY ops,
@ -7591,15 +7522,10 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
return true;
}
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject templateObject(cx);
if (!GetTemplateObjectForNative(cx, script, pc, fun->native(), args, &templateObject))
return false;
IonSpew(IonSpew_BaselineIC, " Generating Call_Native stub (fun=%p, cons=%s)",
fun.get(), constructing ? "yes" : "no");
ICCall_Native::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
fun, templateObject, constructing, pc - script->code);
fun, constructing, pc - script->code);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
@ -9403,20 +9329,16 @@ ICSetPropCallSetter::ICSetPropCallSetter(Kind kind, IonCode *stubCode, HandleSha
}
ICCall_Scripted::ICCall_Scripted(IonCode *stubCode, ICStub *firstMonitorStub,
HandleScript calleeScript, HandleObject templateObject,
uint32_t pcOffset)
HandleScript calleeScript, uint32_t pcOffset)
: ICMonitoredStub(ICStub::Call_Scripted, stubCode, firstMonitorStub),
calleeScript_(calleeScript),
templateObject_(templateObject),
pcOffset_(pcOffset)
{ }
ICCall_Native::ICCall_Native(IonCode *stubCode, ICStub *firstMonitorStub,
HandleFunction callee, HandleObject templateObject,
ICCall_Native::ICCall_Native(IonCode *stubCode, ICStub *firstMonitorStub, HandleFunction callee,
uint32_t pcOffset)
: ICMonitoredStub(ICStub::Call_Native, stubCode, firstMonitorStub),
callee_(callee),
templateObject_(templateObject),
pcOffset_(pcOffset)
{ }

View File

@ -1796,76 +1796,58 @@ class ICNewArray_Fallback : public ICFallbackStub
{
friend class ICStubSpace;
HeapPtrObject templateObject_;
ICNewArray_Fallback(IonCode *stubCode, JSObject *templateObject)
: ICFallbackStub(ICStub::NewArray_Fallback, stubCode), templateObject_(templateObject)
ICNewArray_Fallback(IonCode *stubCode)
: ICFallbackStub(ICStub::NewArray_Fallback, stubCode)
{}
public:
static inline ICNewArray_Fallback *New(ICStubSpace *space, IonCode *code,
JSObject *templateObject) {
static inline ICNewArray_Fallback *New(ICStubSpace *space, IonCode *code) {
if (!code)
return nullptr;
return space->allocate<ICNewArray_Fallback>(code, templateObject);
return space->allocate<ICNewArray_Fallback>(code);
}
class Compiler : public ICStubCompiler {
RootedObject templateObject;
bool generateStubCode(MacroAssembler &masm);
public:
Compiler(JSContext *cx, JSObject *templateObject)
: ICStubCompiler(cx, ICStub::NewArray_Fallback),
templateObject(cx, templateObject)
Compiler(JSContext *cx)
: ICStubCompiler(cx, ICStub::NewArray_Fallback)
{}
ICStub *getStub(ICStubSpace *space) {
return ICNewArray_Fallback::New(space, getStubCode(), templateObject);
return ICNewArray_Fallback::New(space, getStubCode());
}
};
HeapPtrObject &templateObject() {
return templateObject_;
}
};
class ICNewObject_Fallback : public ICFallbackStub
{
friend class ICStubSpace;
HeapPtrObject templateObject_;
ICNewObject_Fallback(IonCode *stubCode, JSObject *templateObject)
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(templateObject)
ICNewObject_Fallback(IonCode *stubCode)
: ICFallbackStub(ICStub::NewObject_Fallback, stubCode)
{}
public:
static inline ICNewObject_Fallback *New(ICStubSpace *space, IonCode *code,
JSObject *templateObject) {
static inline ICNewObject_Fallback *New(ICStubSpace *space, IonCode *code) {
if (!code)
return nullptr;
return space->allocate<ICNewObject_Fallback>(code, templateObject);
return space->allocate<ICNewObject_Fallback>(code);
}
class Compiler : public ICStubCompiler {
RootedObject templateObject;
bool generateStubCode(MacroAssembler &masm);
public:
Compiler(JSContext *cx, JSObject *templateObject)
: ICStubCompiler(cx, ICStub::NewObject_Fallback),
templateObject(cx, templateObject)
Compiler(JSContext *cx)
: ICStubCompiler(cx, ICStub::NewObject_Fallback)
{}
ICStub *getStub(ICStubSpace *space) {
return ICNewObject_Fallback::New(space, getStubCode(), templateObject);
return ICNewObject_Fallback::New(space, getStubCode());
}
};
HeapPtrObject &templateObject() {
return templateObject_;
}
};
// Compare
@ -5222,31 +5204,24 @@ class ICCall_Scripted : public ICMonitoredStub
protected:
HeapPtrScript calleeScript_;
HeapPtrObject templateObject_;
uint32_t pcOffset_;
ICCall_Scripted(IonCode *stubCode, ICStub *firstMonitorStub,
HandleScript calleeScript, HandleObject templateObject,
ICCall_Scripted(IonCode *stubCode, ICStub *firstMonitorStub, HandleScript calleeScript,
uint32_t pcOffset);
public:
static inline ICCall_Scripted *New(
ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
HandleScript calleeScript, HandleObject templateObject,
ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub, HandleScript calleeScript,
uint32_t pcOffset)
{
if (!code)
return nullptr;
return space->allocate<ICCall_Scripted>(code, firstMonitorStub,
calleeScript, templateObject, pcOffset);
return space->allocate<ICCall_Scripted>(code, firstMonitorStub, calleeScript, pcOffset);
}
HeapPtrScript &calleeScript() {
return calleeScript_;
}
HeapPtrObject &templateObject() {
return templateObject_;
}
static size_t offsetOfCalleeScript() {
return offsetof(ICCall_Scripted, calleeScript_);
@ -5288,7 +5263,6 @@ class ICCallScriptedCompiler : public ICCallStubCompiler {
ICStub *firstMonitorStub_;
bool isConstructing_;
RootedScript calleeScript_;
RootedObject templateObject_;
uint32_t pcOffset_;
bool generateStubCode(MacroAssembler &masm);
@ -5297,14 +5271,12 @@ class ICCallScriptedCompiler : public ICCallStubCompiler {
}
public:
ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub,
HandleScript calleeScript, HandleObject templateObject,
bool isConstructing, uint32_t pcOffset)
ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub, HandleScript calleeScript,
bool isConstructing, uint32_t pcOffset)
: ICCallStubCompiler(cx, ICStub::Call_Scripted),
firstMonitorStub_(firstMonitorStub),
isConstructing_(isConstructing),
calleeScript_(cx, calleeScript),
templateObject_(cx, templateObject),
pcOffset_(pcOffset)
{ }
@ -5314,14 +5286,12 @@ class ICCallScriptedCompiler : public ICCallStubCompiler {
firstMonitorStub_(firstMonitorStub),
isConstructing_(isConstructing),
calleeScript_(cx, nullptr),
templateObject_(cx, nullptr),
pcOffset_(pcOffset)
{ }
ICStub *getStub(ICStubSpace *space) {
if (calleeScript_) {
return ICCall_Scripted::New(space, getStubCode(), firstMonitorStub_,
calleeScript_, templateObject_,
return ICCall_Scripted::New(space, getStubCode(), firstMonitorStub_, calleeScript_,
pcOffset_);
}
return ICCall_AnyScripted::New(space, getStubCode(), firstMonitorStub_, pcOffset_);
@ -5334,30 +5304,23 @@ class ICCall_Native : public ICMonitoredStub
protected:
HeapPtrFunction callee_;
HeapPtrObject templateObject_;
uint32_t pcOffset_;
ICCall_Native(IonCode *stubCode, ICStub *firstMonitorStub,
HandleFunction callee, HandleObject templateObject,
ICCall_Native(IonCode *stubCode, ICStub *firstMonitorStub, HandleFunction callee,
uint32_t pcOffset);
public:
static inline ICCall_Native *New(ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
HandleFunction callee, HandleObject templateObject,
uint32_t pcOffset)
HandleFunction callee, uint32_t pcOffset)
{
if (!code)
return nullptr;
return space->allocate<ICCall_Native>(code, firstMonitorStub,
callee, templateObject, pcOffset);
return space->allocate<ICCall_Native>(code, firstMonitorStub, callee, pcOffset);
}
HeapPtrFunction &callee() {
return callee_;
}
HeapPtrObject &templateObject() {
return templateObject_;
}
static size_t offsetOfCallee() {
return offsetof(ICCall_Native, callee_);
@ -5372,7 +5335,6 @@ class ICCall_Native : public ICMonitoredStub
ICStub *firstMonitorStub_;
bool isConstructing_;
RootedFunction callee_;
RootedObject templateObject_;
uint32_t pcOffset_;
bool generateStubCode(MacroAssembler &masm);
@ -5381,20 +5343,17 @@ class ICCall_Native : public ICMonitoredStub
}
public:
Compiler(JSContext *cx, ICStub *firstMonitorStub,
HandleFunction callee, HandleObject templateObject,
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleFunction callee,
bool isConstructing, uint32_t pcOffset)
: ICCallStubCompiler(cx, ICStub::Call_Native),
firstMonitorStub_(firstMonitorStub),
isConstructing_(isConstructing),
callee_(cx, callee),
templateObject_(cx, templateObject),
pcOffset_(pcOffset)
{ }
ICStub *getStub(ICStubSpace *space) {
return ICCall_Native::New(space, getStubCode(), firstMonitorStub_,
callee_, templateObject_, pcOffset_);
return ICCall_Native::New(space, getStubCode(), firstMonitorStub_, callee_, pcOffset_);
}
};
};

View File

@ -383,43 +383,3 @@ BaselineInspector::hasSeenDoubleResult(jsbytecode *pc)
return false;
}
JSObject *
BaselineInspector::getTemplateObject(jsbytecode *pc)
{
if (!hasBaselineScript())
return NULL;
const ICEntry &entry = icEntryFromPC(pc);
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
switch (stub->kind()) {
case ICStub::NewArray_Fallback:
return stub->toNewArray_Fallback()->templateObject();
case ICStub::NewObject_Fallback:
return stub->toNewObject_Fallback()->templateObject();
case ICStub::Call_Scripted:
if (JSObject *obj = stub->toCall_Scripted()->templateObject())
return obj;
break;
default:
break;
}
}
return NULL;
}
JSObject *
BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
{
if (!hasBaselineScript())
return NULL;
const ICEntry &entry = icEntryFromPC(pc);
for (ICStub *stub = entry.firstStub(); stub; stub = stub->next()) {
if (stub->isCall_Native() && stub->toCall_Native()->callee()->native() == native)
return stub->toCall_Native()->templateObject();
}
return NULL;
}

View File

@ -110,9 +110,6 @@ class BaselineInspector
bool hasSeenAccessedGetter(jsbytecode *pc);
bool hasSeenDoubleResult(jsbytecode *pc);
bool hasSeenNonStringIterNext(jsbytecode *pc);
JSObject *getTemplateObject(jsbytecode *pc);
JSObject *getTemplateObjectForNative(jsbytecode *pc, Native native);
};
} // namespace jit

View File

@ -1434,13 +1434,13 @@ IonBuilder::inspectOpcode(JSOp op)
case JSOP_NEWINIT:
if (GET_UINT8(pc) == JSProto_Array)
return jsop_newarray(0);
return jsop_newobject();
return jsop_newobject(nullptr);
case JSOP_NEWARRAY:
return jsop_newarray(GET_UINT24(pc));
case JSOP_NEWOBJECT:
return jsop_newobject();
return jsop_newobject(info().getObject(pc));
case JSOP_INITELEM:
return jsop_initelem();
@ -4634,30 +4634,24 @@ IonBuilder::createThisScriptedSingleton(JSFunction *target, MDefinition *callee)
if (!target->nonLazyScript()->types)
return nullptr;
JSObject *templateObject = inspector->getTemplateObject(pc);
if (!templateObject || !templateObject->is<JSObject>())
return nullptr;
if (templateObject->getProto() != proto)
return nullptr;
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(templateObject)))
return nullptr;
// For template objects with NewScript info, the appropriate allocation
// kind to use may change due to dynamic property adds. In these cases
// calling Ion code will be invalidated, but any baseline template object
// may be stale. Update to the correct template object in this case.
types::TypeObject *templateType = templateObject->type();
if (templateType->hasNewScript()) {
templateObject = templateType->newScript()->templateObject;
JS_ASSERT(templateObject->type() == templateType);
// Trigger recompilation if the templateObject changes.
types::TypeObjectKey::get(templateType)->watchStateChangeForNewScriptTemplate(constraints());
}
// Generate an inline path to create a new |this| object with
// the given singleton prototype.
types::TypeObject *type = cx->getNewType(&JSObject::class_, proto, target);
if (!type)
return nullptr;
if (!types::TypeScript::ThisTypes(target->nonLazyScript())->hasType(types::Type::ObjectType(type)))
return nullptr;
RootedObject targetRoot(cx, target);
JSObject *templateObject = CreateThisForFunctionWithProto(cx, targetRoot, proto, TenuredObject);
if (!templateObject)
return nullptr;
// Trigger recompilation if the templateObject changes.
types::TypeObjectKey *templateType = types::TypeObjectKey::get(templateObject);
if (templateType->newScript())
templateType->watchStateChangeForNewScriptTemplate(constraints());
MCreateThisWithTemplate *createThis = MCreateThisWithTemplate::New(templateObject);
current->add(createThis);
@ -5340,16 +5334,38 @@ IonBuilder::jsop_compare(JSOp op)
return true;
}
JSObject *
IonBuilder::getNewArrayTemplateObject(uint32_t count)
{
NewObjectKind newKind = types::UseNewTypeForInitializer(script(), pc, JSProto_Array);
// Do not allocate template objects in the nursery.
if (newKind == GenericObject)
newKind = TenuredObject;
JSObject *templateObject = NewDenseUnallocatedArray(cx, count, nullptr, newKind);
if (!templateObject)
return nullptr;
if (newKind != SingletonObject) {
types::TypeObject *type = types::TypeScript::InitObject(cx, script(), pc, JSProto_Array);
if (!type)
return nullptr;
templateObject->setType(type);
}
return templateObject;
}
bool
IonBuilder::jsop_newarray(uint32_t count)
{
JS_ASSERT(script()->compileAndGo);
JSObject *templateObject = inspector->getTemplateObject(pc);
JSObject *templateObject = getNewArrayTemplateObject(count);
if (!templateObject)
return abort("No template object for NEWARRAY");
return false;
JS_ASSERT(templateObject->is<ArrayObject>());
if (templateObject->type()->unknownProperties()) {
// We will get confused in jsop_initelem_array if we can't find the
// type object being initialized.
@ -5370,16 +5386,36 @@ IonBuilder::jsop_newarray(uint32_t count)
}
bool
IonBuilder::jsop_newobject()
IonBuilder::jsop_newobject(JSObject *baseObj)
{
// Don't bake in the TypeObject for non-CNG scripts.
JS_ASSERT(script()->compileAndGo);
JSObject *templateObject = inspector->getTemplateObject(pc);
if (!templateObject)
return abort("No template object for NEWOBJECT");
NewObjectKind newKind = types::UseNewTypeForInitializer(script(), pc, JSProto_Object);
// Do not allocate template objects in the nursery.
if (newKind == GenericObject)
newKind = TenuredObject;
JSObject *templateObject;
if (baseObj) {
RootedObject baseObjRoot(cx, baseObj);
templateObject = CopyInitializerObject(cx, baseObjRoot, newKind);
} else {
gc::AllocKind allocKind = GuessObjectGCKind(0);
templateObject = NewBuiltinClassInstance(cx, &JSObject::class_, allocKind, newKind);
}
if (!templateObject)
return false;
if (newKind != SingletonObject) {
types::TypeObject *type = types::TypeScript::InitObject(cx, script(), pc, JSProto_Object);
if (!type)
return false;
templateObject->setType(type);
}
JS_ASSERT(templateObject->is<JSObject>());
MNewObject *ins = MNewObject::New(templateObject,
/* templateObjectIsClassPrototype = */ false);

View File

@ -345,6 +345,7 @@ class IonBuilder : public MIRGenerator
MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind);
JSObject *getNewArrayTemplateObject(uint32_t count);
MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
ArrayBufferView::ViewType viewType);
@ -492,7 +493,7 @@ class IonBuilder : public MIRGenerator
bool jsop_delprop(PropertyName *name);
bool jsop_delelem();
bool jsop_newarray(uint32_t count);
bool jsop_newobject();
bool jsop_newobject(JSObject *baseObj);
bool jsop_initelem();
bool jsop_initelem_array();
bool jsop_initelem_getter_setter();

View File

@ -8,7 +8,6 @@
#include "builtin/ParallelArray.h"
#include "builtin/TestingFunctions.h"
#include "jit/BaselineInspector.h"
#include "jit/IonBuilder.h"
#include "jit/Lowering.h"
#include "jit/MIR.h"
@ -208,17 +207,15 @@ IonBuilder::inlineArray(CallInfo &callInfo)
uint32_t initLength = 0;
MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating;
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js_Array);
if (!templateObject)
return InliningStatus_NotInlined;
JS_ASSERT(templateObject->is<ArrayObject>());
// Multiple arguments imply array initialization, not just construction.
if (callInfo.argc() >= 2) {
initLength = callInfo.argc();
allocating = MNewArray::NewArray_Allocating;
types::TypeObjectKey *type = types::TypeObjectKey::get(templateObject);
types::TypeObject *baseType = types::TypeScript::InitObject(cx, script(), pc, JSProto_Array);
if (!baseType)
return InliningStatus_Error;
types::TypeObjectKey *type = types::TypeObjectKey::get(baseType);
if (!type->unknownProperties()) {
types::HeapTypeSetKey elemTypes = type->property(JSID_VOID);
@ -248,6 +245,10 @@ IonBuilder::inlineArray(CallInfo &callInfo)
callInfo.unwrapArgs();
JSObject *templateObject = getNewArrayTemplateObject(initLength);
if (!templateObject)
return InliningStatus_Error;
types::TemporaryTypeSet::DoubleConversion conversion =
getInlineReturnTypeSet()->convertDoubleElements(constraints());
if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
@ -499,10 +500,10 @@ IonBuilder::inlineArrayConcat(CallInfo &callInfo)
}
// Inline the call.
JSObject *templateObj = inspector->getTemplateObjectForNative(pc, js::array_concat);
if (!templateObj || templateObj->type() != baseThisType)
return InliningStatus_NotInlined;
JS_ASSERT(templateObj->is<ArrayObject>());
JSObject *templateObj = NewDenseEmptyArray(cx, thisType->proto().toObject(), TenuredObject);
if (!templateObj)
return InliningStatus_Error;
templateObj->setType(baseThisType);
callInfo.unwrapArgs();
@ -895,13 +896,13 @@ IonBuilder::inlineStringObject(CallInfo &callInfo)
if (type != MIRType_Int32 && type != MIRType_String)
return InliningStatus_NotInlined;
JSObject *templateObj = inspector->getTemplateObjectForNative(pc, js_String);
if (!templateObj)
return InliningStatus_NotInlined;
JS_ASSERT(templateObj->is<StringObject>());
callInfo.unwrapArgs();
RootedString emptyString(cx, cx->runtime()->emptyString);
JSObject *templateObj = StringObject::create(cx, emptyString, TenuredObject);
if (!templateObj)
return InliningStatus_Error;
MNewStringObject *ins = MNewStringObject::New(callInfo.getArg(0), templateObj);
current->add(ins);
current->push(ins);

View File

@ -1067,15 +1067,15 @@ class ConstraintDataFreezeObjectForInlinedCall
}
};
// Constraint which triggers recompilation when the template object for a
// type's new script changes.
// Constraint which triggers recompilation when the allocation kind of the
// template object for a type's new script changes.
class ConstraintDataFreezeObjectForNewScriptTemplate
{
JSObject *templateObject;
gc::AllocKind allocKind;
public:
ConstraintDataFreezeObjectForNewScriptTemplate(JSObject *templateObject)
: templateObject(templateObject)
ConstraintDataFreezeObjectForNewScriptTemplate(gc::AllocKind allocKind)
: allocKind(allocKind)
{}
const char *kind() { return "freezeObjectForNewScriptTemplate"; }
@ -1083,7 +1083,7 @@ class ConstraintDataFreezeObjectForNewScriptTemplate
bool invalidateOnNewType(Type type) { return false; }
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
bool invalidateOnNewObjectState(TypeObject *object) {
return !object->hasNewScript() || object->newScript()->templateObject != templateObject;
return !object->hasNewScript() || object->newScript()->allocKind != allocKind;
}
bool constraintHolds(JSContext *cx,
@ -1131,9 +1131,9 @@ TypeObjectKey::watchStateChangeForInlinedCall(CompilerConstraintList *constraint
void
TypeObjectKey::watchStateChangeForNewScriptTemplate(CompilerConstraintList *constraints)
{
JSObject *templateObject = asTypeObject()->newScript()->templateObject;
gc::AllocKind kind = asTypeObject()->newScript()->allocKind;
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
constraints->add(IonAlloc()->new_<CompilerConstraintInstance<ConstraintDataFreezeObjectForNewScriptTemplate> >(objectProperty, ConstraintDataFreezeObjectForNewScriptTemplate(templateObject)));
constraints->add(IonAlloc()->new_<CompilerConstraintInstance<ConstraintDataFreezeObjectForNewScriptTemplate> >(objectProperty, ConstraintDataFreezeObjectForNewScriptTemplate(kind)));
}
void
@ -3130,7 +3130,8 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
}
newScript->fun = fun;
newScript->templateObject = baseobj;
newScript->allocKind = kind;
newScript->shape = baseobj->lastProperty();
newScript->initializerList = (TypeNewScript::Initializer *)
((char *) newScript + sizeof(TypeNewScript));

View File

@ -820,15 +820,14 @@ struct TypeNewScript : public TypeObjectAddendum
HeapPtrFunction fun;
/* Allocation kind to use for newly constructed objects. */
gc::AllocKind allocKind;
/*
* Template object to use for newly constructed objects. Reflects all
* definite properties the object will have and the allocation kind to use
* for the object. The allocation kind --- and template object itself ---
* is subject to change if objects allocated with this type are given
* dynamic slots later on due to new properties being added after the
* constructor function finishes.
* Shape to use for newly constructed objects. Reflects all definite
* properties the object will have.
*/
HeapPtrObject templateObject;
HeapPtrShape shape;
/*
* Order in which properties become initialized. We need this in case a

View File

@ -1417,7 +1417,7 @@ TypeNewScript::writeBarrierPre(TypeNewScript *newScript)
JS::Zone *zone = newScript->fun->zoneFromAnyThread();
if (zone->needsBarrier()) {
MarkObject(zone->barrierTracer(), &newScript->fun, "write barrier");
MarkObject(zone->barrierTracer(), &newScript->templateObject, "write barrier");
MarkShape(zone->barrierTracer(), &newScript->shape, "write barrier");
}
#endif
}

View File

@ -1562,19 +1562,15 @@ CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *pa
* which reflects any properties that will definitely be added to the
* object before it is read from.
*/
RootedObject templateObject(cx, type->newScript()->templateObject);
JS_ASSERT(templateObject->type() == type);
RootedObject res(cx, CopyInitializerObject(cx, templateObject, newKind));
gc::AllocKind kind = type->newScript()->allocKind;
RootedObject res(cx, NewObjectWithType(cx, type, parent, kind, newKind));
if (!res)
return nullptr;
if (newKind == SingletonObject) {
Rooted<TaggedProto> proto(cx, templateObject->getProto());
if (!res->splicePrototype(cx, &JSObject::class_, proto))
return NULL;
} else {
res->setType(type);
}
RootedObject metadata(cx, res->getMetadata());
RootedShape shape(cx, type->newScript()->shape);
JS_ALWAYS_TRUE(JSObject::setLastProperty(cx, res, shape));
if (metadata && !JSObject::setMetadata(cx, res, metadata))
return nullptr;
return res;
}
@ -1584,7 +1580,7 @@ CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *pa
JSObject *
js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *proto,
NewObjectKind newKind /* = GenericObject */)
NewObjectKind newKind /* = GenericObject */)
{
RootedObject res(cx);
@ -2528,8 +2524,7 @@ JSObject::growSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount,
* objects are constructed.
*/
if (!obj->hasLazyType() && !oldCount && obj->type()->hasNewScript()) {
JSObject *oldTemplate = obj->type()->newScript()->templateObject;
gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(oldTemplate->numFixedSlots());
gc::AllocKind kind = obj->type()->newScript()->allocKind;
uint32_t newScriptSlots = gc::GetGCKindSlots(kind);
if (newScriptSlots == obj->numFixedSlots() &&
gc::TryIncrementAllocKind(&kind) &&
@ -2539,12 +2534,13 @@ JSObject::growSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount,
AutoEnterAnalysis enter(ncx);
Rooted<TypeObject*> typeObj(cx, obj->type());
RootedShape shape(cx, oldTemplate->lastProperty());
RootedShape shape(cx, typeObj->newScript()->shape);
JSObject *reshapedObj = NewReshapedObject(ncx, typeObj, obj->getParent(), kind, shape);
if (!reshapedObj)
return false;
typeObj->newScript()->templateObject = reshapedObj;
typeObj->newScript()->allocKind = kind;
typeObj->newScript()->shape = reshapedObj->lastProperty();
typeObj->markStateChange(ncx);
}
}