зеркало из https://github.com/mozilla/gecko-dev.git
Bug 964915 part 2 - Refactor IonBuilder to pass obj as argument to getProp* methods. r=efaust
This commit is contained in:
Родитель
e7ac1c18d7
Коммит
c6b3bf5b1f
|
@ -6586,18 +6586,12 @@ IonBuilder::jsop_getgname(PropertyName *name)
|
|||
return true;
|
||||
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
// Spoof the stack to call into the getProp path.
|
||||
// First, make sure there's room.
|
||||
if (!current->ensureHasSlots(1))
|
||||
return false;
|
||||
pushConstant(ObjectValue(*obj));
|
||||
if (!getPropTryCommonGetter(&succeeded, name, types))
|
||||
MDefinition *globalObj = constant(ObjectValue(*obj));
|
||||
if (!getPropTryCommonGetter(&succeeded, globalObj, name, types))
|
||||
return false;
|
||||
if (succeeded)
|
||||
return true;
|
||||
|
||||
// Clean up the pushed global object if we were not sucessful.
|
||||
current->pop();
|
||||
return jsop_getname(name);
|
||||
}
|
||||
|
||||
|
@ -8162,25 +8156,6 @@ IonBuilder::jsop_arguments()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_arguments_length()
|
||||
{
|
||||
// Type Inference has guaranteed this is an optimized arguments object.
|
||||
MDefinition *args = current->pop();
|
||||
args->setImplicitlyUsedUnchecked();
|
||||
|
||||
// We don't know anything from the callee
|
||||
if (inliningDepth_ == 0) {
|
||||
MInstruction *ins = MArgumentsLength::New(alloc());
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We are inlining and know the number of arguments the callee pushed
|
||||
return pushConstant(Int32Value(inlineCallInfo_->argv().length()));
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_rest()
|
||||
{
|
||||
|
@ -8579,20 +8554,19 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
|||
{
|
||||
bool emitted = false;
|
||||
|
||||
MDefinition *obj = current->pop();
|
||||
|
||||
// Try to optimize arguments.length.
|
||||
if (!getPropTryArgumentsLength(&emitted) || emitted)
|
||||
if (!getPropTryArgumentsLength(&emitted, obj) || emitted)
|
||||
return emitted;
|
||||
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
current->peek(-1), name, types);
|
||||
|
||||
// Always use a call if we are performing analysis and
|
||||
// not actually emitting code, to simplify later analysis. Also skip deeper
|
||||
// analysis if there are no known types for this operation, as it will
|
||||
// always invalidate when executing.
|
||||
if (info().executionModeIsAnalysis() || types->empty()) {
|
||||
MDefinition *obj = current->peek(-1);
|
||||
MCallGetProperty *call = MCallGetProperty::New(alloc(), obj, name, *pc == JSOP_CALLPROP);
|
||||
current->add(call);
|
||||
|
||||
|
@ -8601,41 +8575,42 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
|||
// In this case we still need the getprop call so that the later
|
||||
// analysis knows when the |this| value has been read from.
|
||||
if (info().executionModeIsAnalysis()) {
|
||||
if (!getPropTryConstant(&emitted, name, types) || emitted)
|
||||
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
|
||||
return emitted;
|
||||
}
|
||||
|
||||
current->pop();
|
||||
current->push(call);
|
||||
return resumeAfter(call) && pushTypeBarrier(call, types, BarrierKind::TypeSet);
|
||||
}
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, name, types);
|
||||
|
||||
// Try to hardcode known constants.
|
||||
if (!getPropTryConstant(&emitted, name, types) || emitted)
|
||||
if (!getPropTryConstant(&emitted, obj, name, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit loads from known binary data blocks
|
||||
if (!getPropTryTypedObject(&emitted, name, types) || emitted)
|
||||
if (!getPropTryTypedObject(&emitted, obj, name, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit loads from definite slots.
|
||||
if (!getPropTryDefiniteSlot(&emitted, name, barrier, types) || emitted)
|
||||
if (!getPropTryDefiniteSlot(&emitted, obj, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to inline a common property getter, or make a call.
|
||||
if (!getPropTryCommonGetter(&emitted, name, types) || emitted)
|
||||
if (!getPropTryCommonGetter(&emitted, obj, name, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit a monomorphic/polymorphic access based on baseline caches.
|
||||
if (!getPropTryInlineAccess(&emitted, name, barrier, types) || emitted)
|
||||
if (!getPropTryInlineAccess(&emitted, obj, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit a polymorphic cache.
|
||||
if (!getPropTryCache(&emitted, name, barrier, types) || emitted)
|
||||
if (!getPropTryCache(&emitted, obj, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Emit a call.
|
||||
MDefinition *obj = current->pop();
|
||||
MCallGetProperty *call = MCallGetProperty::New(alloc(), obj, name, *pc == JSOP_CALLPROP);
|
||||
current->add(call);
|
||||
current->push(call);
|
||||
|
@ -8646,12 +8621,12 @@ IonBuilder::jsop_getprop(PropertyName *name)
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryArgumentsLength(bool *emitted)
|
||||
IonBuilder::getPropTryArgumentsLength(bool *emitted, MDefinition *obj)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
if (current->peek(-1)->type() != MIRType_MagicOptimizedArguments) {
|
||||
if (obj->type() != MIRType_MagicOptimizedArguments) {
|
||||
if (script()->argumentsHasVarBinding() &&
|
||||
current->peek(-1)->mightBeType(MIRType_MagicOptimizedArguments))
|
||||
obj->mightBeType(MIRType_MagicOptimizedArguments))
|
||||
{
|
||||
return abort("Type is not definitely lazy arguments.");
|
||||
}
|
||||
|
@ -8661,11 +8636,23 @@ IonBuilder::getPropTryArgumentsLength(bool *emitted)
|
|||
return true;
|
||||
|
||||
*emitted = true;
|
||||
return jsop_arguments_length();
|
||||
|
||||
obj->setImplicitlyUsedUnchecked();
|
||||
|
||||
// We don't know anything from the callee
|
||||
if (inliningDepth_ == 0) {
|
||||
MInstruction *ins = MArgumentsLength::New(alloc());
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We are inlining and know the number of arguments the callee pushed
|
||||
return pushConstant(Int32Value(inlineCallInfo_->argv().length()));
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryConstant(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
|
@ -8674,11 +8661,9 @@ IonBuilder::getPropTryConstant(bool *emitted, PropertyName *name,
|
|||
return true;
|
||||
|
||||
bool testObject, testString;
|
||||
if (!testSingletonPropertyTypes(current->peek(-1), singleton, name, &testObject, &testString))
|
||||
if (!testSingletonPropertyTypes(obj, singleton, name, &testObject, &testString))
|
||||
return true;
|
||||
|
||||
MDefinition *obj = current->pop();
|
||||
|
||||
// Property access is a known constant -- safe to emit.
|
||||
JS_ASSERT(!testString || !testObject);
|
||||
if (testObject)
|
||||
|
@ -8695,14 +8680,13 @@ IonBuilder::getPropTryConstant(bool *emitted, PropertyName *name,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryTypedObject(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryTypedObject(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *resultTypes)
|
||||
{
|
||||
TypeDescrSet fieldDescrs;
|
||||
int32_t fieldOffset;
|
||||
size_t fieldIndex;
|
||||
if (!lookupTypedObjectField(current->peek(-1), name, &fieldOffset,
|
||||
&fieldDescrs, &fieldIndex))
|
||||
if (!lookupTypedObjectField(obj, name, &fieldOffset, &fieldDescrs, &fieldIndex))
|
||||
return false;
|
||||
if (fieldDescrs.empty())
|
||||
return true;
|
||||
|
@ -8718,6 +8702,7 @@ IonBuilder::getPropTryTypedObject(bool *emitted, PropertyName *name,
|
|||
case TypeDescr::Struct:
|
||||
case TypeDescr::SizedArray:
|
||||
return getPropTryComplexPropOfTypedObject(emitted,
|
||||
obj,
|
||||
fieldOffset,
|
||||
fieldDescrs,
|
||||
fieldIndex,
|
||||
|
@ -8725,6 +8710,7 @@ IonBuilder::getPropTryTypedObject(bool *emitted, PropertyName *name,
|
|||
|
||||
case TypeDescr::Scalar:
|
||||
return getPropTryScalarPropOfTypedObject(emitted,
|
||||
obj,
|
||||
fieldOffset,
|
||||
fieldDescrs,
|
||||
resultTypes);
|
||||
|
@ -8737,26 +8723,23 @@ IonBuilder::getPropTryTypedObject(bool *emitted, PropertyName *name,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted,
|
||||
IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
TypeDescrSet fieldDescrs,
|
||||
types::TemporaryTypeSet *resultTypes)
|
||||
{
|
||||
// Must always be loading the same scalar type
|
||||
// Must always be loading the same scalar type.
|
||||
ScalarTypeDescr::Type fieldType;
|
||||
if (!fieldDescrs.scalarType(&fieldType))
|
||||
return true;
|
||||
|
||||
// OK, perform the optimization
|
||||
|
||||
MDefinition *typedObj = current->pop();
|
||||
|
||||
// OK, perform the optimization.
|
||||
return pushScalarLoadFromTypedObject(emitted, typedObj, constantInt(fieldOffset),
|
||||
fieldType, true);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted,
|
||||
IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
TypeDescrSet fieldDescrs,
|
||||
size_t fieldIndex,
|
||||
|
@ -8769,8 +8752,6 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted,
|
|||
|
||||
// OK, perform the optimization
|
||||
|
||||
MDefinition *typedObj = current->pop();
|
||||
|
||||
// Identify the type object for the field.
|
||||
MDefinition *type = loadTypedObjectType(typedObj);
|
||||
MDefinition *fieldTypeObj = typeObjectForFieldFromStructType(type, fieldIndex);
|
||||
|
@ -8780,15 +8761,14 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool *emitted,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
types::HeapTypeSetKey property;
|
||||
if (!getDefiniteSlot(current->peek(-1)->resultTypeSet(), name, &property))
|
||||
if (!getDefiniteSlot(obj->resultTypeSet(), name, &property))
|
||||
return true;
|
||||
|
||||
MDefinition *obj = current->pop();
|
||||
MDefinition *useObj = obj;
|
||||
if (obj->type() != MIRType_Object) {
|
||||
MGuardObject *guard = MGuardObject::New(alloc(), obj);
|
||||
|
@ -8811,7 +8791,7 @@ IonBuilder::getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryCommonGetter(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
|
@ -8822,7 +8802,7 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, PropertyName *name,
|
|||
if (!foundProto)
|
||||
return true;
|
||||
|
||||
types::TemporaryTypeSet *objTypes = current->peek(-1)->resultTypeSet();
|
||||
types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
|
||||
MDefinition *guard = testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
|
||||
foundProto, lastProperty);
|
||||
if (!guard)
|
||||
|
@ -8830,8 +8810,6 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, PropertyName *name,
|
|||
|
||||
bool isDOM = objTypes->isDOMClass();
|
||||
|
||||
MDefinition *obj = current->pop();
|
||||
|
||||
if (isDOM && testShouldDOMCall(objTypes, commonGetter, JSJitInfo::Getter)) {
|
||||
const JSJitInfo *jitinfo = commonGetter->jitInfo();
|
||||
MInstruction *get;
|
||||
|
@ -8947,11 +8925,11 @@ GetPropertyShapes(jsid id, const BaselineInspector::ShapeVector &shapes,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
if (current->peek(-1)->type() != MIRType_Object)
|
||||
if (obj->type() != MIRType_Object)
|
||||
return true;
|
||||
|
||||
BaselineInspector::ShapeVector shapes(alloc());
|
||||
|
@ -8965,7 +8943,6 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
|
|||
if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
|
||||
rvalType = MIRType_Value;
|
||||
|
||||
MDefinition *obj = current->pop();
|
||||
if (shapes.length() == 1) {
|
||||
// In the monomorphic case, use separate ShapeGuard and LoadSlot
|
||||
// instructions.
|
||||
|
@ -9033,13 +9010,11 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, PropertyName *name,
|
|||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
|
||||
IonBuilder::getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types)
|
||||
{
|
||||
JS_ASSERT(*emitted == false);
|
||||
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
// The input value must either be an object, or we should have strong suspicions
|
||||
// that it can be safely unboxed to an object.
|
||||
if (obj->type() != MIRType_Object) {
|
||||
|
@ -9061,7 +9036,6 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name,
|
|||
if (barrier == BarrierKind::NoBarrier)
|
||||
barrier = PropertyReadOnPrototypeNeedsTypeBarrier(constraints(), obj, name, types);
|
||||
|
||||
current->pop();
|
||||
MGetPropertyCache *load = MGetPropertyCache::New(alloc(), obj, name,
|
||||
barrier != BarrierKind::NoBarrier);
|
||||
|
||||
|
|
|
@ -398,27 +398,27 @@ class IonBuilder : public MIRGenerator
|
|||
MIRType slotType = MIRType_None);
|
||||
|
||||
// jsop_getprop() helpers.
|
||||
bool getPropTryArgumentsLength(bool *emitted);
|
||||
bool getPropTryConstant(bool *emitted, PropertyName *name,
|
||||
bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj);
|
||||
bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
bool getPropTryDefiniteSlot(bool *emitted, PropertyName *name,
|
||||
bool getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
bool getPropTryCommonGetter(bool *emitted, PropertyName *name,
|
||||
bool getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *types);
|
||||
bool getPropTryInlineAccess(bool *emitted, PropertyName *name,
|
||||
bool getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
bool getPropTryTypedObject(bool *emitted, PropertyName *name,
|
||||
bool getPropTryTypedObject(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted,
|
||||
bool getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
TypeDescrSet fieldTypeReprs,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryComplexPropOfTypedObject(bool *emitted,
|
||||
bool getPropTryComplexPropOfTypedObject(bool *emitted, MDefinition *typedObj,
|
||||
int32_t fieldOffset,
|
||||
TypeDescrSet fieldTypeReprs,
|
||||
size_t fieldIndex,
|
||||
types::TemporaryTypeSet *resultTypes);
|
||||
bool getPropTryCache(bool *emitted, PropertyName *name,
|
||||
bool getPropTryCache(bool *emitted, MDefinition *obj, PropertyName *name,
|
||||
BarrierKind barrier, types::TemporaryTypeSet *types);
|
||||
bool needsToMonitorMissingProperties(types::TemporaryTypeSet *types);
|
||||
|
||||
|
@ -590,7 +590,6 @@ class IonBuilder : public MIRGenerator
|
|||
bool jsop_length();
|
||||
bool jsop_length_fastPath();
|
||||
bool jsop_arguments();
|
||||
bool jsop_arguments_length();
|
||||
bool jsop_arguments_getelem();
|
||||
bool jsop_runonce();
|
||||
bool jsop_rest();
|
||||
|
|
Загрузка…
Ссылка в новой задаче