mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset b4ebfef56fee (bug 922270) for SM(r) failures.
This commit is contained in:
parent
4dc9ae61b0
commit
83dc48b96b
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{ }
|
||||
|
||||
|
@ -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_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user