Bug 1322091 part 3 - Port Baseline ArgumentsObject GETELEM stub to CacheIR. r=evilpie

--HG--
extra : rebase_source : b113f160c23ed4743b592b1d5d007a46b62393fb
This commit is contained in:
Jan de Mooij 2016-12-09 12:20:30 -10:00
Родитель bde1c4947f
Коммит dc38fe3f57
7 изменённых файлов: 79 добавлений и 179 удалений

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

@ -1624,6 +1624,49 @@ BaselineCacheIRCompiler::emitLoadFrameArgumentResult()
return true;
}
bool
BaselineCacheIRCompiler::emitLoadArgumentsObjectArgResult()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Get initial length value.
masm.unboxInt32(Address(obj, ArgumentsObject::getInitialLengthSlotOffset()), scratch);
// Ensure no overridden length/element.
masm.branchTest32(Assembler::NonZero,
scratch,
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
failure->label());
// Bounds check.
masm.rshift32(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch);
masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
// Load ArgumentsData.
masm.loadPrivate(Address(obj, ArgumentsObject::getDataSlotOffset()), scratch);
// Fail if we have a RareArgumentsData (elements were deleted).
masm.branchPtr(Assembler::NotEqual,
Address(scratch, offsetof(ArgumentsData, rareData)),
ImmWord(0),
failure->label());
// Guard the argument is not a FORWARD_TO_CALL_SLOT MagicValue. Note that
// the order here matters: we should only clobber R0 after emitting the last
// guard.
BaseValueIndex argValue(scratch, index, ArgumentsData::offsetOfArgs());
masm.branchTestMagic(Assembler::Equal, argValue, failure->label());
masm.loadValue(argValue, R0);
return true;
}
bool
BaselineCacheIRCompiler::emitTypeMonitorResult()
{

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

@ -865,18 +865,6 @@ TypedArrayGetElemStubExists(ICGetElem_Fallback* stub, HandleObject obj)
return false;
}
static bool
ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which which)
{
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
if (!iter->isGetElem_Arguments())
continue;
if (iter->toGetElem_Arguments()->which() == which)
return true;
}
return false;
}
static bool
IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
{
@ -955,27 +943,6 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
return true;
RootedObject obj(cx, &lhs.toObject());
// Check for ArgumentsObj[int] accesses
if (obj->is<ArgumentsObject>() && rhs.isInt32() &&
!obj->as<ArgumentsObject>().hasOverriddenElement())
{
ICGetElem_Arguments::Which which = ICGetElem_Arguments::Mapped;
if (obj->is<UnmappedArgumentsObject>())
which = ICGetElem_Arguments::Unmapped;
if (!ArgumentsGetElemStubExists(stub, which)) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(ArgsObj[Int32]) stub");
ICGetElem_Arguments::Compiler compiler(
cx, stub->fallbackMonitorStub()->firstMonitorStub(), which);
ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
if (!argsStub)
return false;
stub->addNewStub(argsStub);
*attached = true;
return true;
}
}
// Check for NativeObject[int] dense accesses.
if (IsNativeDenseElementAccess(obj, rhs)) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
@ -1339,93 +1306,6 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
return true;
}
//
// GetElem_Arguments
//
bool
ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
MOZ_ASSERT(which_ == ICGetElem_Arguments::Mapped ||
which_ == ICGetElem_Arguments::Unmapped);
const Class* clasp = (which_ == ICGetElem_Arguments::Mapped)
? &MappedArgumentsObject::class_
: &UnmappedArgumentsObject::class_;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
// Guard on input being an arguments object.
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
Register objReg = masm.extractObject(R0, ExtractTemp0);
masm.branchTestObjClass(Assembler::NotEqual, objReg, scratchReg, clasp, &failure);
// Guard on index being int32
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
Register idxReg = masm.extractInt32(R1, ExtractTemp1);
// Get initial ArgsObj length value.
masm.unboxInt32(Address(objReg, ArgumentsObject::getInitialLengthSlotOffset()), scratchReg);
// Test if length or any element have been overridden.
masm.branchTest32(Assembler::NonZero,
scratchReg,
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
&failure);
// Length has not been overridden, ensure that R1 is an integer and is <= length.
masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratchReg);
masm.branch32(Assembler::AboveOrEqual, idxReg, scratchReg, &failure);
// Length check succeeded, now check the correct bit. We clobber potential type regs
// now. Inputs will have to be reconstructed if we fail after this point, but that's
// unlikely.
Label failureReconstructInputs;
regs = availableGeneralRegs(0);
regs.takeUnchecked(objReg);
regs.takeUnchecked(idxReg);
regs.take(scratchReg);
Register argData = regs.takeAny();
// Load ArgumentsData
masm.loadPrivate(Address(objReg, ArgumentsObject::getDataSlotOffset()), argData);
// Fail if we have a RareArgumentsData (elements were deleted).
masm.branchPtr(Assembler::NotEqual,
Address(argData, offsetof(ArgumentsData, rareData)),
ImmWord(0),
&failureReconstructInputs);
// Load the value. Use scratchReg to form a ValueOperand to load into.
masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData);
regs.add(scratchReg);
ValueOperand tempVal = regs.takeAnyValue();
masm.loadValue(BaseValueIndex(argData, idxReg), tempVal);
// Makesure that this is not a FORWARD_TO_CALL_SLOT magic value.
masm.branchTestMagic(Assembler::Equal, tempVal, &failureReconstructInputs);
// Copy value from temp to R0.
masm.moveValue(tempVal, R0);
// Type-check result
EmitEnterTypeMonitorIC(masm);
// Failed, but inputs are deconstructed into object and int, and need to be
// reconstructed into values.
masm.bind(&failureReconstructInputs);
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
masm.tagValue(JSVAL_TYPE_INT32, idxReg, R1);
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// SetElem_Fallback
//
@ -7299,13 +7179,6 @@ ICGetElem_TypedArray::ICGetElem_TypedArray(JitCode* stubCode, Shape* shape, Scal
MOZ_ASSERT(extra_ == type);
}
/* static */ ICGetElem_Arguments*
ICGetElem_Arguments::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetElem_Arguments& other)
{
return New<ICGetElem_Arguments>(cx, space, other.jitCode(), firstMonitorStub, other.which());
}
ICSetElem_DenseOrUnboxedArray::ICSetElem_DenseOrUnboxedArray(JitCode* stubCode, Shape* shape, ObjectGroup* group)
: ICUpdatedStub(SetElem_DenseOrUnboxedArray, stubCode),
shape_(shape),

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

@ -560,53 +560,6 @@ class ICGetElem_TypedArray : public ICStub
};
};
class ICGetElem_Arguments : public ICMonitoredStub
{
friend class ICStubSpace;
public:
enum Which { Mapped, Unmapped };
private:
ICGetElem_Arguments(JitCode* stubCode, ICStub* firstMonitorStub, Which which)
: ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
{
extra_ = static_cast<uint16_t>(which);
}
public:
static ICGetElem_Arguments* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetElem_Arguments& other);
Which which() const {
return static_cast<Which>(extra_);
}
class Compiler : public ICStubCompiler {
ICStub* firstMonitorStub_;
Which which_;
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
virtual int32_t getKey() const {
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(which_) << 17);
}
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, Which which)
: ICStubCompiler(cx, ICStub::GetElem_Arguments, Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
which_(which)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICGetElem_Arguments>(space, getStubCode(), firstMonitorStub_, which_);
}
};
};
// SetElem
// JSOP_SETELEM
// JSOP_INITELEM

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

@ -52,7 +52,6 @@ namespace jit {
_(GetElem_Dense) \
_(GetElem_UnboxedArray) \
_(GetElem_TypedArray) \
_(GetElem_Arguments) \
\
_(SetElem_Fallback) \
_(SetElem_DenseOrUnboxedArray) \

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

@ -1016,10 +1016,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
case ICStub::GetProp_Generic:
return MIRType::Value;
case ICStub::GetElem_Arguments:
// Either an object or magic arguments.
return MIRType::Value;
case ICStub::GetElem_Dense:
case ICStub::GetElem_TypedArray:
case ICStub::GetElem_UnboxedArray:

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

@ -85,6 +85,13 @@ GetPropIRGenerator::tryAttachStub()
return true;
if (tryAttachProxy(obj, objId, id))
return true;
return false;
}
if (idVal_.isInt32()) {
ValOperandId indexId = getElemKeyValueId();
if (tryAttachArgumentsObjectArg(obj, objId, indexId))
return true;
return false;
}
return false;
}
@ -850,6 +857,28 @@ GetPropIRGenerator::tryAttachMagicArgument(ValOperandId valId, ValOperandId inde
return true;
}
bool
GetPropIRGenerator::tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId,
ValOperandId indexId)
{
MOZ_ASSERT(idVal_.isInt32());
if (!obj->is<ArgumentsObject>() || obj->as<ArgumentsObject>().hasOverriddenElement())
return false;
if (obj->is<MappedArgumentsObject>()) {
writer.guardClass(objId, GuardClassKind::MappedArguments);
} else {
MOZ_ASSERT(obj->is<UnmappedArgumentsObject>());
writer.guardClass(objId, GuardClassKind::UnmappedArguments);
}
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
writer.loadArgumentsObjectArgResult(objId, int32IndexId);
writer.typeMonitorResult();
return true;
}
void
GetPropIRGenerator::maybeEmitIdGuard(jsid id)
{

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

@ -161,6 +161,7 @@ enum class CacheKind : uint8_t
_(LoadTypedObjectResult) \
_(LoadInt32ArrayLengthResult) \
_(LoadUnboxedArrayLengthResult) \
_(LoadArgumentsObjectArgResult) \
_(LoadArgumentsObjectLengthResult) \
_(LoadStringCharResult) \
_(LoadStringLengthResult) \
@ -521,6 +522,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
void loadUnboxedArrayLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
}
void loadArgumentsObjectArgResult(ObjOperandId obj, Int32OperandId index) {
writeOpWithOperandId(CacheOp::LoadArgumentsObjectArgResult, obj);
writeOperandId(index);
}
void loadArgumentsObjectLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
}
@ -651,7 +656,9 @@ class MOZ_RAII GetPropIRGenerator
bool tryAttachStringChar(ValOperandId valId, ValOperandId indexId);
bool tryAttachStringLength(ValOperandId valId, HandleId id);
bool tryAttachMagicArgumentsName(ValOperandId valId, HandleId id);
bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
bool tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId, ValOperandId indexId);
ValOperandId getElemKeyValueId() const {
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);