Bug 964915 part 2 - Refactor IonBuilder to pass obj as argument to getProp* methods. r=efaust

This commit is contained in:
Jan de Mooij 2014-05-08 15:00:45 +02:00
Родитель e7ac1c18d7
Коммит c6b3bf5b1f
2 изменённых файлов: 57 добавлений и 84 удалений

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

@ -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();