Bug 903394 - IonMonkey: Refactor IonBuilder jsop_setelem, r=jandem

This commit is contained in:
Hannes Verschore 2013-08-10 02:46:27 +02:00
parent a945ebb57d
commit a47a37c46a
2 changed files with 176 additions and 111 deletions

View File

@ -6918,75 +6918,31 @@ IonBuilder::jsop_getelem_string()
bool
IonBuilder::jsop_setelem()
{
bool emitted = false;
MDefinition *value = current->pop();
MDefinition *index = current->pop();
MDefinition *object = current->pop();
int arrayType = TypedArrayObject::TYPE_MAX;
if (ElementAccessIsTypedArray(object, index, &arrayType))
return jsop_setelem_typed(arrayType, SetElem_Normal,
object, index, value);
if (!setElemTryTypedStatic(&emitted, object, index, value) || emitted)
return emitted;
if (ElementAccessIsDenseNative(object, index)) {
do {
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
break;
if (!object->resultTypeSet())
break;
if (!setElemTryTyped(&emitted, object, index, value) || emitted)
return emitted;
types::StackTypeSet::DoubleConversion conversion =
object->resultTypeSet()->convertDoubleElements(cx);
if (!setElemTryDense(&emitted, object, index, value) || emitted)
return emitted;
// If AmbiguousDoubleConversion, only handle int32 values for now.
if (conversion == types::StackTypeSet::AmbiguousDoubleConversion &&
value->type() != MIRType_Int32)
{
break;
}
// Don't generate a fast path if there have been bounds check failures
// and this access might be on a sparse property.
if (ElementAccessHasExtraIndexedProperty(cx, object) && failedBoundsCheck_)
break;
return jsop_setelem_dense(conversion, SetElem_Normal, object, index, value);
} while(false);
}
if (object->type() == MIRType_Magic)
return jsop_arguments_setelem(object, index, value);
if (!setElemTryArguments(&emitted, object, index, value) || emitted)
return emitted;
if (script()->argumentsHasVarBinding() && object->mightBeType(MIRType_Magic))
return abort("Type is not definitely lazy arguments.");
// Check if only objects are manipulated valid index, and generate a SetElementCache.
do {
if (!object->mightBeType(MIRType_Object))
break;
if (!index->mightBeType(MIRType_Int32) &&
!index->mightBeType(MIRType_String))
{
break;
}
// TODO: Bug 876650: remove this check:
// Temporary disable the cache if non dense native,
// untill the cache supports more ics
SetElemICInspector icInspect(inspector->setElemICInspector(pc));
if (!icInspect.sawDenseWrite())
break;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
break;
MInstruction *ins = MSetElementCache::New(object, index, value, script()->strict);
current->add(ins);
current->push(value);
return resumeAfter(ins);
} while (false);
if (!setElemTryCache(&emitted, object, index, value) || emitted)
return emitted;
// Emit call.
MInstruction *ins = MCallSetElement::New(object, index, value);
current->add(ins);
current->push(value);
@ -6994,6 +6950,157 @@ IonBuilder::jsop_setelem()
return resumeAfter(ins);
}
bool
IonBuilder::setElemTryTypedStatic(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value)
{
JS_ASSERT(*emitted == false);
int arrayType = TypedArrayObject::TYPE_MAX;
if (!ElementAccessIsTypedArray(object, index, &arrayType))
return true;
if (!LIRGenerator::allowStaticTypedArrayAccesses())
return true;
if (ElementAccessHasExtraIndexedProperty(cx, object))
return true;
if (!object->resultTypeSet())
return true;
JSObject *tarrObj = object->resultTypeSet()->getSingleton();
if (!tarrObj)
return true;
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(tarr);
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(index, viewType);
if (!ptr)
return true;
// Emit StoreTypedArrayElementStatic.
object->setFoldedUnchecked();
// Clamp value to [0, 255] for Uint8ClampedArray.
MDefinition *toWrite = value;
if (viewType == ArrayBufferView::TYPE_UINT8_CLAMPED) {
toWrite = MClampToUint8::New(value);
current->add(toWrite->toInstruction());
}
MInstruction *store = MStoreTypedArrayElementStatic::New(tarr, ptr, toWrite);
current->add(store);
current->push(value);
if (!resumeAfter(store))
return false;
*emitted = true;
return true;
}
bool
IonBuilder::setElemTryTyped(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value)
{
JS_ASSERT(*emitted == false);
int arrayType = TypedArrayObject::TYPE_MAX;
if (!ElementAccessIsTypedArray(object, index, &arrayType))
return true;
// Emit typed setelem variant.
if (!jsop_setelem_typed(arrayType, SetElem_Normal, object, index, value))
return false;
*emitted = true;
return true;
}
bool
IonBuilder::setElemTryDense(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value)
{
JS_ASSERT(*emitted == false);
if (!ElementAccessIsDenseNative(object, index))
return true;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
return true;
if (!object->resultTypeSet())
return true;
types::StackTypeSet::DoubleConversion conversion =
object->resultTypeSet()->convertDoubleElements(cx);
// If AmbiguousDoubleConversion, only handle int32 values for now.
if (conversion == types::StackTypeSet::AmbiguousDoubleConversion &&
value->type() != MIRType_Int32)
{
return true;
}
// Don't generate a fast path if there have been bounds check failures
// and this access might be on a sparse property.
if (ElementAccessHasExtraIndexedProperty(cx, object) && failedBoundsCheck_)
return true;
// Emit dense setelem variant.
if (!jsop_setelem_dense(conversion, SetElem_Normal, object, index, value))
return false;
*emitted = true;
return true;
}
bool
IonBuilder::setElemTryArguments(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value)
{
JS_ASSERT(*emitted == false);
if (object->type() != MIRType_Magic)
return true;
// Arguments are not supported yet.
return abort("NYI arguments[]=");
}
bool
IonBuilder::setElemTryCache(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value)
{
JS_ASSERT(*emitted == false);
if (!object->mightBeType(MIRType_Object))
return true;
if (!index->mightBeType(MIRType_Int32) && !index->mightBeType(MIRType_String))
return true;
// TODO: Bug 876650: remove this check:
// Temporary disable the cache if non dense native,
// untill the cache supports more ics
SetElemICInspector icInspect(inspector->setElemICInspector(pc));
if (!icInspect.sawDenseWrite())
return true;
if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
return true;
// Emit SetElementCache.
MInstruction *ins = MSetElementCache::New(object, index, value, script()->strict);
current->add(ins);
current->push(value);
if (!resumeAfter(ins))
return false;
*emitted = true;
return true;
}
bool
IonBuilder::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion,
SetElemSafety safety,
@ -7105,57 +7212,12 @@ IonBuilder::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion,
return true;
}
bool
IonBuilder::jsop_setelem_typed_static(MDefinition *obj, MDefinition *id, MDefinition *value,
bool *psucceeded)
{
if (!LIRGenerator::allowStaticTypedArrayAccesses())
return true;
if (ElementAccessHasExtraIndexedProperty(cx, obj))
return true;
if (!obj->resultTypeSet())
return true;
JSObject *tarrObj = obj->resultTypeSet()->getSingleton();
if (!tarrObj)
return true;
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(tarr);
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(id, viewType);
if (!ptr)
return true;
obj->setFoldedUnchecked();
// Clamp value to [0, 255] for Uint8ClampedArray.
MDefinition *toWrite = value;
if (viewType == ArrayBufferView::TYPE_UINT8_CLAMPED) {
toWrite = MClampToUint8::New(value);
current->add(toWrite->toInstruction());
}
MInstruction *store = MStoreTypedArrayElementStatic::New(tarr, ptr, toWrite);
current->add(store);
current->push(value);
*psucceeded = true;
return resumeAfter(store);
}
bool
IonBuilder::jsop_setelem_typed(int arrayType,
SetElemSafety safety,
MDefinition *obj, MDefinition *id, MDefinition *value)
{
bool staticAccess = false;
if (!jsop_setelem_typed_static(obj, id, value, &staticAccess))
return false;
if (staticAccess)
return true;
bool expectOOB;
if (safety == SetElem_Normal) {
SetElemICInspector icInspect(inspector->setElemICInspector(pc));
@ -7357,12 +7419,6 @@ IonBuilder::jsop_arguments_getelem()
return abort("NYI inlined not constant get argument element");
}
bool
IonBuilder::jsop_arguments_setelem(MDefinition *object, MDefinition *index, MDefinition *value)
{
return abort("NYI arguments[]=");
}
static JSObject *
CreateRestArgumentsTemplateObject(JSContext *cx, unsigned length)
{

View File

@ -367,6 +367,18 @@ class IonBuilder : public MIRGenerator
bool getPropTryCache(bool *emitted, HandlePropertyName name, HandleId id,
bool barrier, types::StackTypeSet *types);
// jsop_setelem() helpers.
bool setElemTryTyped(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value);
bool setElemTryTypedStatic(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value);
bool setElemTryDense(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value);
bool setElemTryArguments(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value);
bool setElemTryCache(bool *emitted, MDefinition *object,
MDefinition *index, MDefinition *value);
// Typed array helpers.
MInstruction *getTypedArrayLength(MDefinition *obj);
MInstruction *getTypedArrayElements(MDefinition *obj);
@ -411,14 +423,11 @@ class IonBuilder : public MIRGenerator
bool jsop_setelem_typed(int arrayType,
SetElemSafety safety,
MDefinition *object, MDefinition *index, MDefinition *value);
bool jsop_setelem_typed_static(MDefinition *object, MDefinition *index, MDefinition *value,
bool *psucceeded);
bool jsop_length();
bool jsop_length_fastPath();
bool jsop_arguments();
bool jsop_arguments_length();
bool jsop_arguments_getelem();
bool jsop_arguments_setelem(MDefinition *object, MDefinition *index, MDefinition *value);
bool jsop_runonce();
bool jsop_rest();
bool jsop_not();